home *** CD-ROM | disk | FTP | other *** search
/ MacHack 1997 / MacHack 1997.toast / Hacks / Hacks ’94 / [√] Distribution Restricted! / Christian Ruse / Fourier Paper + Apps / nih-image154_source.sea / V1.54 Source / File1.p < prev    next >
Text File  |  1994-01-31  |  91KB  |  3,237 lines

  1. unit File1;
  2.  
  3. {Routines used by Image for implementing File Menu commands.}
  4.  
  5. interface
  6.  
  7.  
  8.     uses
  9.         QuickDraw, Palettes, PictUtil, PrintTraps, globals, Utilities, Graphics, file2, sound, Lut, Text;
  10.  
  11.  
  12.     function CloseAWindow (WhichWindow: WindowPtr): integer;
  13.     procedure DoClose;
  14.     function OpenFile (fname: str255; vnum: integer): boolean;
  15.     function OpenPict (fname: str255; vnum: integer; Reverting: boolean): boolean;
  16.     procedure SaveFile;
  17.     function DoOpen (FileName: str255; RefNum: integer): boolean;
  18.     function ImportFile (FileName: str255; RefNum: integer): boolean;
  19.     procedure RevertToSaved;
  20.     procedure SaveAs (name: str255; RefNum: integer);
  21.     procedure Export (name: str255; RefNum: integer);
  22.     procedure FindWhatToPrint;
  23.     procedure UpdateFileMenu;
  24.     procedure SaveAsText (fname: str255; RefNum: integer);
  25.     procedure SaveAll;
  26.     procedure UpdateWindowsMenuItem (PicSize: LongInt; title: str255; PicNum: integer);
  27.     procedure SaveScreen;
  28.     function OpenPICS (name: str255; fRefNum: integer): boolean;
  29.     procedure RescaleToEightBits;
  30.  
  31.  
  32. implementation
  33.  
  34.     var
  35.         OpenAllFiles, UseExistingLUT, PICTReadErr, UpdateIcons: boolean;
  36.         SaveRefNum: integer;
  37.         TempStackInfo: StackInfoRec;
  38.         PictSrcRect: rect;
  39.  
  40. {$PUSH}
  41. {$D-}
  42.  
  43.     procedure LookForCluts (fname: str255; vnum: integer);
  44.         var
  45.             RefNum: integer;
  46.             err: OSErr;
  47.             ok1, ok2: boolean;
  48.     begin
  49.         if not UseExistingLUT then begin
  50.                 err := SetVol(nil, vnum);
  51.                 refNum := OpenResFile(fname);
  52.                 if RefNum <> -1 then begin
  53.                         ok1 := LoadCLUTResource(KlutzID);
  54.                         if not ok1 then
  55.                             ok2 := LoadCLUTResource(PixelPaintID);
  56.                         CloseResFile(refNum);
  57.                     end;
  58.             end;
  59.     end;
  60.  
  61.  
  62.     function OpenImageHeader (f: integer; fname: str255; vnum: integer): boolean;
  63.         var
  64.             ByteCount: LongInt;
  65.             err: OSErr;
  66.             TempHdr: PicHeader;
  67.             i, OldNExtra, p1x, p2x: integer;
  68.             ok: boolean;
  69.             hUnitsKind: UnitsType;
  70.     begin
  71.         ByteCount := HeaderSize;
  72.         err := SetFPos(f, fsFromStart, info^.HeaderOffset);
  73.         err := fsread(f, ByteCount, @TempHdr);
  74.         if CheckIO(err) <> NoErr then begin
  75.                 OpenImageHeader := false;
  76.                 exit(OpenImageHeader);
  77.             end;
  78.         with info^, TempHdr do begin
  79.                 if PictureType <> TiffFile then begin
  80.                         nlines := hnlines;
  81.                         PixelsPerLine := hPixelsPerLine;
  82.                     end;
  83.                 if (hversion > 54) and not UseExistingLUT then begin
  84.                         OldNExtra := nExtraColors;
  85.                         nExtraColors := hnExtraColors;
  86.                         ExtraColors := hExtraColors;
  87.                         if (nExtraColors > 0) or (OldNExtra <> nExtraColors) then
  88.                             RedrawLUTWindow;
  89.                     end;
  90.                 if (hversion >= 42) and not UseExistingLUT then begin
  91.                         if hversion < 142 then begin
  92.                                 LUTMode := hOldLUTMode;
  93.                                 if (LutMode = OldAppleDefault) or (LutMode = OldSpectrum) then
  94.                                     LutMode := ColorLut;
  95.                             end
  96.                         else begin
  97.                                 LUTMode := hLUTMode;
  98.                                 if LutMode = Pseudocolor then begin
  99.                                         if ((hnColors > 32) and (hTable = CustomTable)) or (hTable > spectrum) then
  100.                                             LutMode := ColorLut;
  101.                                     end;
  102.                             end;
  103.                         case LUTMode of
  104.                             PseudoColor: 
  105.                                 if hversion < 142 then begin
  106.                                         nColors := hOldnColors;
  107.                                         for i := 0 to ncolors - 1 do begin
  108.                                                 RedLUT[i] := hr[i];
  109.                                                 GreenLUT[i] := hg[i];
  110.                                                 BlueLUT[i] := hb[i];
  111.                                             end;
  112.                                         ColorEnd := 255 - hOldColorStart;
  113.                                         ColorStart := ColorEnd - nColors * hColorWidth + 1;
  114.                                         if ColorStart < 0 then
  115.                                             ColorStart := 0;
  116.                                         InvertPalette;
  117.                                         FillColor1 := BlackRGB;
  118.                                         FillColor2 := BlackRGB;
  119.                                         ColorTable := CustomTable;
  120.                                         UpdateLUT;
  121.                                     end
  122.                                 else begin {V1.42 or later}
  123.                                         if (hTable <> CustomTable) and (hTable <= spectrum) then begin
  124.                                                 SwitchColorTables(GetColorTableItem(hTable), false);
  125.                                                 if hInvertedTable then
  126.                                                     InvertPalette;
  127.                                             end
  128.                                         else begin
  129.                                                 nColors := hnColors;
  130.                                                 ColorTable := CustomTable;
  131.                                                 if nColors <= 32 then
  132.                                                     for i := 0 to ncolors - 1 do begin
  133.                                                             RedLUT[i] := hr[i];
  134.                                                             GreenLUT[i] := hg[i];
  135.                                                             BlueLUT[i] := hb[i];
  136.                                                         end;
  137.                                             end;
  138.                                         ColorStart := hColorStart;
  139.                                         ColorEnd := hColorEnd;
  140.                                         FillColor1 := hFill1;
  141.                                         FillColor2 := hFill2;
  142.                                         UpdateLUT;
  143.                                         UpdateMap;
  144.                                     end; {v1.42 or later}
  145.                             GrayScale: 
  146.                                 ResetGrayMap;
  147.                             ColorLut, CustomGrayscale: 
  148.                                 if PictureType <> PictFile then begin
  149.                                         if ColorMapOffset > 0 then
  150.                                             GetTiffColorMap(f)
  151.                                         else
  152.                                             LookForCluts(fname, vnum);
  153.                                     end;
  154.                             otherwise
  155.                         end; {case}
  156.                         if hLutMode = CustomGrayscale then
  157.                             LutMode := CustomGrayscale;
  158.                     end;{if}
  159.                 if (hversion >= 65) and ((ForegroundIndex <> hForegroundIndex) or (BackgroundIndex <> hBackgroundIndex)) then begin
  160.                         SetForegroundColor(hForegroundIndex);
  161.                         SetBackgroundColor(hBackgroundIndex);
  162.                     end;
  163.                 if (hversion > 88) and (LUTMode = GrayScale) and not UseExistingLUT then begin
  164.                         if hversion < 138 then begin
  165.                                 p1x := 255 - hp2x;
  166.                                 p2x := 255 - hp1x;
  167.                             end
  168.                         else begin
  169.                                 p1x := hp1x;
  170.                                 p2x := hp2x
  171.                             end;
  172.                         nColors := 256;
  173.                         ColorStart := p1x;
  174.                         ColorEnd := p2x;
  175.                         UpdateLUT;
  176.                     end;
  177.                 if hversion > 106 then begin
  178.                         xSpatialScale := hXSpatialScale;
  179.                         ySpatialScale := xSpatialScale;
  180.                         PixelAspectRatio := 1.0;
  181.                         SpatiallyCalibrated := xSpatialScale <> 0.0;
  182.                     end;
  183.                 if hversion > 140 then begin
  184.                         PixelAspectRatio := hPixelAspectRatio;
  185.                         ySpatialScale := xSpatialScale / PixelAspectRatio;
  186.                     end;
  187.                 if hversion > 153 then
  188.                     xUnit := hXUnit
  189.                 else begin
  190.                         hUnitsKind := UnitsType(hUnitsID - 5);
  191.                         GetXUnits(hUnitsKind);
  192.                     end;
  193.                 if ((hnCoefficients > 0) and (hfit < UncalibratedOD)) or (hfit = UncalibratedOD) then begin
  194.                         if (hfit = SpareFit1) or (hfit = SpareFit2) then begin
  195.                                 DensityCalibrated := false;
  196.                                 DrawLabels('', '', '');
  197.                             end
  198.                         else begin
  199.                                 fit := hfit;
  200.                                 if hfit <> UncalibratedOD then begin
  201.                                         nCoefficients := hnCoefficients;
  202.                                         Coefficient := hCoeff;
  203.                                     end;
  204.                                 UnitOfMeasure := hUM;
  205.                                 DensityCalibrated := true;
  206.                                 if hversion >= 144 then
  207.                                     ZeroClip := hZeroClip
  208.                                 else
  209.                                     ZeroClip := false;
  210.                                 GenerateValues;
  211.                             end;
  212.                     end
  213.                 else begin
  214.                         DensityCalibrated := false;
  215.                         DrawLabels('', '', '');
  216.                     end;
  217.                 BinaryPic := hBinaryPic;
  218.                 if hSliceEnd > 1 then begin
  219.                         SliceStart := hSliceStart;
  220.                         SliceEnd := hSliceEnd;
  221.                         if SliceEnd > 254 then
  222.                             SliceEnd := 254;
  223.                     end;
  224.                 if hNSlices > 1 then begin
  225.                         with TempStackInfo do begin
  226.                                 nSlices := hNSlices;
  227.                                 if nSlices > MaxSlices then
  228.                                     nSlices := MaxSlices;
  229.                                 CurrentSlice := hCurrentSlice;
  230.                                 if (hCurrentSlice < 1) or (hCurrentSlice > nSlices) then
  231.                                     CurrentSlice := 1;
  232.                                 SliceSpacing := hSliceSpacing;
  233.                                 LoopTime := hLoopTime;
  234.                             end;
  235.                     end;
  236.                 iVersion := hVersion;
  237.                 OpenImageHeader := true
  238.             end;
  239.     end;
  240.  
  241.  
  242.     function OpenHeader (f: integer; fname: str255; vnum: integer; var NextTiffIFD: LongInt): boolean;
  243.         var
  244.             ByteCount, FileSize, DirOffset, MaxImages: LongInt;
  245.             hdr: packed array[1..512] of byte;
  246.             err: OSErr;
  247.             TempHdr: PicHeader;
  248.             TiffInfo: TiffInfoRec;
  249.     begin
  250.         with info^ do begin
  251.                 if (WhatToOpen = OpenUnknown) or (WhatToOpen = OpenImported) then begin
  252.                         err := SetFPos(f, fsFromStart, 0);
  253.                         ByteCount := 8;
  254.                         err := fsread(f, ByteCount, @hdr);
  255.                         if ((hdr[1] = 73) and (hdr[2] = 73)) or ((hdr[1] = 77) and (hdr[2] = 77)) then
  256.                             WhatToOpen := OpenTIFF
  257.                         else if WhatToOpen = OpenUnknown then
  258.                             WhatToOpen := OpenImage
  259.                         else
  260.                             WhatToOpen := OpenMCID;
  261.                     end;
  262.                 StackInfo := nil;
  263.                 with TempStackInfo do begin
  264.                         nSlices := 0;
  265.                         CurrentSlice := 1;
  266.                         SliceSpacing := 0.0;
  267.                         LoopTime := 0.0;
  268.                     end;
  269.                 NextTiffIFD := 0;
  270.                 iVersion := 0;
  271.                 case WhatToOpen of
  272.                     OpenImage:  begin
  273.                             err := SetFPos(f, fsFromStart, 0);
  274.                             ByteCount := 8;
  275.                             err := fsread(f, ByteCount, @TempHdr);
  276.                             if TempHdr.FileID = FileID8 then begin
  277.                                     HeaderOffset := 0;
  278.                                     PictureType := normal
  279.                                 end
  280.                             else begin
  281.                                     HeaderOffset := -1;
  282.                                     BlockMove(@TempHdr, @hdr, 8);
  283.                                     nlines := hdr[1] + hdr[2] * 256;
  284.                                     PixelsPerLine := hdr[3] + hdr[4] * 256;
  285.                                     PictureType := PDP11;
  286.                                 end;
  287.                             ImageDataOffset := 512;
  288.                         end;
  289.                     OpenMCID:  begin
  290.                             err := SetFPos(f, fsFromStart, 0);
  291.                             ByteCount := 4;
  292.                             err := fsread(f, ByteCount, @hdr);
  293.                             PixelsPerLine := hdr[1] + hdr[2] * 256 + 1;
  294.                             if PixelsPerLine > MaxLine then begin
  295.                                     beep;
  296.                                     PixelsPerLine := MaxLine;
  297.                                 end;
  298.                             nlines := hdr[3] + hdr[4] * 256 + 1;
  299.                             PictureType := imported;
  300.                             LUTMode := grayscale;
  301.                             HeaderOffset := -1;
  302.                             ImageDataOffset := 4;
  303.                         end;
  304.                     OpenCustom:  begin
  305.                             err := GetEof(f, FileSize);
  306.                             if macro then begin
  307.                                     if (ImportCustomOffset + LongInt(ImportCustomWidth) * ImportCustomHeight) > FileSize then begin
  308.                                             macro := false;
  309.                                             OpenHeader := false;
  310.                                             exit(OpenHeader)
  311.                                         end;
  312.                                 end;
  313.                             PixelsPerLine := ImportCustomWidth;
  314.                             nlines := ImportCustomHeight;
  315.                             PictureType := imported;
  316.                             HeaderOffset := -1;
  317.                             ImageDataOffset := ImportCustomOffset;
  318.                             if ImportCustomSlices > 1 then
  319.                                 with TempStackInfo do begin
  320.                                         nSlices := ImportCustomSlices;
  321.                                         MaxImages := (FileSize - ImportCustomOffset) div (LongInt(ImportCustomWidth) * ImportCustomHeight);
  322.                                         if nSlices > MaxImages then
  323.                                             nSlices := MaxImages;
  324.                                         if nSlices < 2 then
  325.                                             nSlices := 0;
  326.                                     end;
  327.                         end;
  328.                     OpenPICT2:  begin
  329.                             err := SetFPos(f, fsFromStart, 0);
  330.                             ByteCount := 8;
  331.                             err := fsread(f, ByteCount, @TempHdr);
  332.                             if TempHdr.FileID = FileID8 then
  333.                                 HeaderOffset := 0
  334.                             else
  335.                                 HeaderOffset := -1;
  336.                             PictureType := PictFile;
  337.                             if not UseExistingLUT then
  338.                                 LutMode := ColorLut;
  339.                             ImageDataOffset := 512;
  340.                         end;
  341.                     OpenTIFF:  begin
  342.                             if not OpenTiffHeader(f, DirOffset) then begin
  343.                                     OpenHeader := false;
  344.                                     exit(OpenHeader)
  345.                                 end;
  346.                             if not OpenTiffDirectory(f, DirOffset, TiffInfo) then begin
  347.                                     OpenHeader := false;
  348.                                     exit(OpenHeader)
  349.                                 end;
  350.                             with TiffInfo do begin
  351.                                     PictureType := TiffFile;
  352.                                     PixelsPerLine := width;
  353.                                     nlines := height;
  354.                                     if BitsPerPixel = 4 then
  355.                                         PictureType := FourBitTiff;
  356.                                     ImageDataOffset := OffsetToData;
  357.                                     if ZeroIsBlack and (PictureType <> FourBitTIFF) then
  358.                                         PictureType := InvertedTiff;
  359.                                     if resolution > 0.0 then begin
  360.                                             case ResUnits of
  361.                                                 tNoUnits: 
  362.                                                     xUnit := 'pixel';
  363.                                                 tCentimeters: 
  364.                                                     xUnit := 'cm';
  365.                                                 tInches: 
  366.                                                     xUnit := 'inch';
  367.                                             end;
  368.                                             xSpatialScale := resolution;
  369.                                             ySpatialScale := resolution;
  370.                                             PixelAspectRatio := 1.0;
  371.                                             if xUnit <> 'pixel' then
  372.                                                 SpatiallyCalibrated := true;
  373.                                         end;
  374.                                     ColorMapOffset := OffsetToColorMap;
  375.                                     HeaderOffset := OffsetToImageHeader;
  376.                                     NextTiffIFD := NextIFD;
  377.                                 end;
  378.                             if not UseExistingLUT then
  379.                                 LutMode := Grayscale;
  380.                         end;
  381.                 end; {case}
  382.                 if HeaderOffset <> -1 then begin
  383.                         if not OpenImageHeader(f, fname, vnum) then begin
  384.                                 OpenHeader := false;
  385.                                 exit(OpenHeader)
  386.                             end
  387.                     end
  388.                 else if (ColorMapOffset > 0) and not UseExistingLUT then
  389.                     GetTiffColorMap(f);
  390.             end; {with}
  391.         OpenHeader := true;
  392.     end;
  393.  
  394.  
  395.     function SaveHeader (f, slines, sPixelsPerLine, vnum: integer; fname: str255; SavingSelection, SavingTIFF: boolean): OSErr;
  396.         var
  397.             TempHdr: PicHeader;
  398.             DummyHdr: array[1..128] of LongInt;
  399.             i: integer;
  400.             ByteCount: LongInt;
  401.             position: LongInt;
  402.             err: OSErr;
  403.             str: str255;
  404.             UnitsKind: UnitsType;
  405.             UnitsPerCM: double;
  406.     begin
  407.         with TempHdr, info^ do begin
  408.                 for i := 1 to 128 do
  409.                     DummyHdr[i] := 0;
  410.                 BlockMove(@DummyHdr, @TempHdr, HeaderSize);
  411.                 FileID := FileID8;
  412.                 hnlines := nlines;
  413.                 hPixelsPerLine := PixelsPerLine;
  414.                 hversion := version;
  415.                 hLUTMode := LUTMode;
  416.                 hOldLutMode := LutMode;
  417.                 hnColors := ncolors;
  418.                 hOldnColors := 0;
  419.                 if LutMode = Pseudocolor then begin
  420.                         hOldLutMode := ColorLut;
  421.                         if (ColorTable = CustomTable) and (ncolors <= 32) then
  422.                             for i := 0 to nColors - 1 do begin
  423.                                     hr[i] := RedLUT[i];
  424.                                     hg[i] := GreenLUT[i];
  425.                                     hb[i] := BlueLUT[i];
  426.                                 end;
  427.                     end;
  428.                 hColorStart := ColorStart;
  429.                 hColorEnd := ColorEnd;
  430.                 hFill1 := FillColor1;
  431.                 hFill2 := FillColor2;
  432.                 hTable := ColorTable;
  433.                 hInvertedTable := InvertedColorTable;
  434.                 hOldColorStart := 255 - ColorEnd;
  435.                 if nColors > 0 then
  436.                     hColorWidth := (ColorEnd - ColorStart) div nColors
  437.                 else
  438.                     hColorWidth := 1;
  439.                 hnExtraColors := nExtraColors;
  440.                 hExtraColors := ExtraColors;
  441.                 hForegroundIndex := ForegroundIndex;
  442.                 hBackgroundIndex := BackgroundIndex;
  443.                 hXSpatialScale := xSpatialScale;
  444.                 hScaleMagnification := 1.0;
  445.                 hPixelAspectRatio := PixelAspectRatio;
  446.                 hUnitsID := 14; {Pixels. For backward compatibility only since hUnits no longer used.}
  447.                 if SpatiallyCalibrated then begin
  448.                         GetUnitsKind(UnitsKind, UnitsPerCM);
  449.                         hUnitsID := ord(UnitsKind) + 5;
  450.                         if hUnitsID > 14 then
  451.                             hUnitsID := 14;
  452.                     end;
  453.                 FindPoints(hp1x, hp1y, hp2x, hp2y);
  454.                 if not DensityCalibrated then
  455.                     hnCoefficients := 0
  456.                 else
  457.                     hnCoefficients := nCoefficients;
  458.                 hfit := fit;
  459.                 hCoeff := Coefficient;
  460.                 hZeroClip := ZeroClip;
  461.                 hUM := UnitOfMeasure;
  462.                 hBinaryPic := BinaryPic;
  463.                 hSliceStart := SliceStart;
  464.                 hSliceEnd := SliceEnd;
  465.                 if StackInfo <> nil then
  466.                     with StackInfo^ do begin
  467.                             hNSlices := nSlices;
  468.                             hSliceSpacing := SliceSpacing;
  469.                             hCurrentSlice := CurrentSlice;
  470.                             hLoopTime := LoopTime;
  471.                         end
  472.                 else begin
  473.                         hNSlices := 0;
  474.                         hSliceSpacing := 0.0;
  475.                         hCurrentSlice := 0;
  476.                         hLoopTime := 0.0;
  477.                     end;
  478.                 hXUnit := xUnit;
  479.                 ByteCount := SizeOf(TempHdr);
  480.                 if ByteCount <> HeaderSize then begin
  481.                         NumToString(ByteCount, str);
  482.                         PutMessage('Internal error check: header size is incorrect.');
  483.                         ExitToShell;
  484.                     end;
  485.                 if SavingSelection then begin
  486.                         hnlines := slines;
  487.                         hPixelsPerLine := sPixelsPerLine;
  488.                     end;
  489.                 err := fswrite(f, ByteCount, @TempHdr);
  490.                 SaveHeader := CheckIO(err);
  491.             end; {with}
  492.     end;
  493.  
  494.  
  495.     procedure PackLines;
  496.   {For odd width images, removes the extra bytes at the end of each line required to make RowBytes even.}
  497.         var
  498.             i: integer;
  499.             SrcPtr, DstPtr: ptr;
  500.     begin
  501.         with info^ do begin
  502.                 SrcPtr := ptr(ord4(PicBaseAddr) + BytesPerRow);
  503.                 DstPtr := ptr(ord4(PicBaseAddr) + PixelsPerLine);
  504.                 for i := 1 to nlines - 1 do begin
  505.                         BlockMove(SrcPtr, DstPtr, PixelsPerLine);
  506.                         SrcPtr := ptr(ord4(SrcPtr) + BytesPerRow);
  507.                         DstPtr := ptr(ord4(DstPtr) + PixelsPerLine);
  508.                     end;
  509.             end;
  510.     end;
  511.  
  512.  
  513.     procedure UnpackLines;
  514.   {For odd width images, adds an extra byte to each line so RowBytes is even.}
  515.         var
  516.             i: integer;
  517.             SrcPtr, DstPtr: ptr;
  518.     begin
  519.         with info^ do begin
  520.                 SrcPtr := ptr(ord4(PicBaseAddr) + LongInt(nlines - 1) * PixelsPerLine);
  521.                 DstPtr := ptr(ord4(PicBaseAddr) + LongInt(nlines - 1) * BytesPerRow);
  522.                 for i := 1 to nlines - 1 do begin
  523.                         BlockMove(SrcPtr, DstPtr, PixelsPerLine);
  524.                         SrcPtr := ptr(ord4(SrcPtr) - PixelsPerLine);
  525.                         DstPtr := ptr(ord4(DstPtr) - BytesPerRow);
  526.                     end;
  527.             end;
  528.     end;
  529.  
  530.  
  531.     function WriteSlices (f: integer): integer;
  532.         var
  533.             ByteCount, SelectionSize: LongInt;
  534.             i, err, SaveCS: integer;
  535.     begin
  536.         with info^, Info^.StackInfo^ do begin
  537.                 SaveCS := CurrentSlice;
  538.                 for i := 1 to nSlices do begin
  539.                         CurrentSlice := i;
  540.                         SelectSlice(CurrentSlice);
  541.                         UpdateTitleBar;
  542.                         ByteCount := ImageSize;
  543.                         if odd(PixelsPerLine) then
  544.                             PackLines;
  545.                         err := fswrite(f, ByteCount, PicBaseAddr);
  546.                         if odd(PixelsPerLine) then
  547.                             UnpackLines;
  548.                         if err <> 0 then
  549.                             leave;
  550.                     end;
  551.                 CurrentSlice := SaveCS;
  552.                 SelectSlice(CurrentSlice);
  553.                 UpdateTitleBar;
  554.                 WriteSlices := err;
  555.             end;
  556.     end;
  557.  
  558.  
  559.     procedure WriteSelection (f: integer; sLines, sPixelsPerLine: LongInt);
  560.   {Contributed by Edward J. Huff(huff@mcclb0.med.nyu.edu).}
  561.         var
  562.             size, offset, ByteCount, BytesDone: LongInt;
  563.             src, dst: ptr;
  564.             err: OSErr;
  565.     begin
  566.         if sPixelsPerLine > UndoBufSize then
  567.             exit(WriteSelection);
  568.         size := sLines * sPixelsPerLine;
  569.         with info^, info^.RoiRect do begin
  570.                 offset := LongInt(top) * BytesPerRow + left;
  571.                 src := ptr(ord4(PicBaseAddr) + offset);
  572.                 BytesDone := 0;
  573.                 while BytesDone < size do begin
  574.                         ByteCount := 0;
  575.                         dst := UndoBuf;
  576.                         while ((ByteCount + sPixelsPerLine) < UndoBufSize) and (BytesDone < size) do begin
  577.                                 BlockMove(src, dst, sPixelsPerLine);
  578.                                 src := ptr(ord4(src) + BytesPerRow);
  579.                                 dst := ptr(ord4(dst) + sPixelsPerLine);
  580.                                 ByteCount := ByteCount + sPixelsPerLine;
  581.                                 BytesDone := BytesDone + sPixelsPerLine;
  582.                             end;
  583.                         err := fswrite(f, ByteCount, UndoBuf);
  584.                     end;
  585.                 SetupUndo; {Needed for drawing roi outline}
  586.             end
  587.     end;
  588.  
  589.  
  590.     function SaveTiffFile (fname: str255; vnum: integer; slines, sPixelsPerLine: integer; SavingSelection: boolean): boolean;
  591.         var
  592.             f, err, i, width, height: integer;
  593.             HdrSize, ByteCount, ctabSize, StackTiffDirSize, ImageDataSize: LongInt;
  594.             TheInfo: FInfo;
  595.             MCIDHeader: packed array[1..4] of byte;
  596.             SaveColorMap: boolean;
  597.     begin
  598.         SaveTiffFile := false;
  599.         ShowWatch;
  600.         err := fsopen(fname, vNum, f);
  601.         if CheckIO(err) <> 0 then
  602.             exit(SaveTiffFile);
  603.         with Info^ do begin
  604.                 SaveColorMap := (LutMode <> Grayscale) and (SaveAsWhat <> asRawData);
  605.                 if SaveAsWhat = SaveAsMCID then begin
  606.                         if SavingSelection then begin
  607.                                 width := sPixelsPerLine;
  608.                                 height := slines;
  609.                             end
  610.                         else begin
  611.                                 width := PixelsPerLine;
  612.                                 height := nLines;
  613.                             end;
  614.                         MCIDHeader[1] := (width - 1) mod 256;
  615.                         MCIDHeader[2] := (width - 1) div 256;
  616.                         MCIDHeader[3] := (height - 1) mod 256;
  617.                         MCIDHeader[4] := (height - 1) div 256;
  618.                         ByteCount := 4;
  619.                         err := fswrite(f, ByteCount, @MCIDHeader);
  620.                     end;
  621.                 HeaderOffset := TiffDirSize;
  622.                 ImageDataOffset := TiffDirSize + HeaderSize;
  623.                 if SaveColorMap then
  624.                     ctabSize := SizeOf(TiffColorMapType)
  625.                 else
  626.                     ctabSize := 0;
  627.                 StackTiffDirSize := 0;
  628.                 if SavingSelection then
  629.                     ImageDataSize := LongInt(slines) * sPixelsPerLine
  630.                 else if StackInfo <> nil then begin
  631.                         ImageDataSize := ImageSize * StackInfo^.nSlices;
  632.                         StackTiffDirSize := SizeOf(StackIFDType) * (StackInfo^.nSlices - 1)
  633.                     end
  634.                 else
  635.                     ImageDataSize := ImageSize;
  636.                 if (SaveAsWhat <> asRawData) and (SaveAsWhat <> SaveAsMCID) then begin
  637.                         if SaveTiffDir(f, slines, sPixelsPerLine, SavingSelection, ctabSize, ImageDataSize) <> NoErr then begin
  638.                                 err := fsclose(f);
  639.                                 err := FSDelete(fname, vnum);
  640.                                 exit(SaveTiffFile)
  641.                             end;
  642.                         err := SetFPos(f, FSFromStart, TiffDirSize);
  643.                         if SaveHeader(f, slines, sPixelsPerLine, vnum, fname, SavingSelection, true) <> NoErr then begin
  644.                                 err := fsclose(f);
  645.                                 err := FSDelete(fname, vnum);
  646.                                 exit(SaveTiffFile)
  647.                             end;
  648.                     end;
  649.                 if SaveAsWhat = SaveAsMCID then
  650.                     KillRoi;
  651.                 if SavingSelection then
  652.                     WriteSelection(f, sLines, sPixelsPerLine)
  653.                 else if StackInfo <> nil then
  654.                     err := WriteSlices(f)
  655.                 else begin
  656.                         ByteCount := ImageDataSize;
  657.                         if odd(PixelsPerLine) then
  658.                             PackLines;
  659.                         err := fswrite(f, ByteCount, PicBaseAddr);
  660.                         if odd(PixelsPerLine) then
  661.                             UnpackLines;
  662.                     end;
  663.                 if SaveAsWhat = SaveAsMCID then
  664.                     InvertPic;
  665.                 if CheckIO(err) <> 0 then begin
  666.                         err := fsclose(f);
  667.                         err := FSDelete(fname, vnum);
  668.                         exit(SaveTiffFile)
  669.                     end;
  670.                 if SaveAsWhat = asRawData then
  671.                     HdrSize := 0
  672.                 else if SaveAsWhat = SaveAsMCID then begin
  673.                         HdrSize := 4;
  674.                         SaveAsWhat := asRawData;
  675.                     end
  676.                 else
  677.                     HdrSize := HeaderSize + TiffDirSize;
  678.                 if SaveColorMap then
  679.                     SaveTiffColorMap(f, ImageDataSize);
  680.                 if StackTiffDirSize > 0 then
  681.                     err := WriteExtraTiffIFDs(f, ImageDataSize, cTabSize);
  682.                 err := SetEOF(f, HdrSize + ImageDataSize + ctabSize + StackTiffDirSize);
  683.                 err := fsclose(f);
  684.                 err := GetFInfo(fname, vnum, TheInfo);
  685.                 if TheInfo.fdCreator <> 'Imag' then begin
  686.                         TheInfo.fdCreator := 'Imag';
  687.                         err := SetFInfo(fname, vnum, TheInfo);
  688.                     end;
  689.                 if SaveAsWhat = asRawData then begin
  690.                         TheInfo.fdType := 'RawD';
  691.                         err := SetFInfo(fname, vnum, TheInfo);
  692.                     end
  693.                 else if TheInfo.fdType <> 'TIFF' then begin
  694.                         TheInfo.fdType := 'TIFF';
  695.                         err := SetFInfo(fname, vnum, TheInfo);
  696.                     end;
  697.                 err := FlushVol(nil, vNum);
  698.                 if not SavingSelection then begin
  699.                         if (PictureType <> BlankField) and (PictureType <> FrameGrabberType) and (PictureType <> ScionType) and (SaveAsWhat <> asRawData) then begin
  700.                                 PictureType := TiffFile;
  701.                                 title := fname;
  702.                                 vref := vnum;
  703.                                 UpdateTitleBar;
  704.                                 if StackInfo = nil then
  705.                                     revertable := true;
  706.                             end;
  707.                     end;
  708.                 if SaveAsWhat <> asRawData then
  709.                     Changes := false;
  710.             end; {with}
  711.         SaveTiffFile := true;
  712.     end;
  713.  
  714.  
  715.     procedure UpdateWindowsMenuItem (PicSize: LongInt; title: str255; PicNum: integer);
  716.         var
  717.             str: str255;
  718.     begin
  719.         NumToString((PicSize + 511) div 1024, str);
  720.         str := concat(title, '  ', str, 'K');
  721.         SetItem(WindowsMenuH, PicNum + WindowsMenuItems + nTextWindows, str);
  722.     end;
  723.  
  724.  
  725.     procedure SaveAsTIFF (fname: str255; RefNum: integer; slines, sPixelsPerLine: integer; SavingSelection: boolean);
  726.         var
  727.             err: integer;
  728.             TheInfo: FInfo;
  729.             replacing, ok: boolean;
  730.             name: str255;
  731.     begin
  732.         err := GetFInfo(fname, RefNum, TheInfo);
  733.         case err of
  734.             NoErr: 
  735.                 with TheInfo do begin
  736.                         if (fdType <> 'TIFF') and (fdType <> 'PICT') and (fdType <> 'IPIC') and (fdType <> 'RawD') and (fdType <> 'PICS') then begin
  737.                                 TypeMismatch(fname);
  738.                                 exit(SaveAsTIFF)
  739.                             end;
  740.                         replacing := true;
  741.                     end;
  742.             FNFerr:  begin
  743.                     if SaveAsWhat = asRawData then
  744.                         err := create(fname, RefNum, 'Imag', 'RawD')
  745.                     else
  746.                         err := create(fname, RefNum, 'Imag', 'TIFF');
  747.                     if CheckIO(err) <> 0 then
  748.                         exit(SaveAsTIFF);
  749.                     replacing := false;
  750.                 end;
  751.             otherwise
  752.                 if CheckIO(err) <> 0 then
  753.                     exit(SaveAsTIFF);
  754.         end;
  755.         if replacing then
  756.             if not RoomForFile(fname, RefNum, slines, sPixelsPerLine, SavingSelection) then
  757.                 exit(SaveAsTIFF);
  758.         ok := SaveTiffFile(fname, RefNum, slines, sPixelsPerLine, SavingSelection);
  759.         if ok then
  760.             with info^ do
  761.                 if StackInfo <> nil then
  762.                     UpdateWindowsMenuItem(PixMapSize * StackInfo^.nSlices, title, PicNum)
  763.                 else
  764.                     UpdateWindowsMenuItem(PixMapSize, title, PicNum);
  765.         with info^ do
  766.             if SavingSelection and Replacing and (PictureType <> BlankField) and (PictureType <> FrameGrabberType) and (PictureType <> ScionType) then
  767.                 PictureType := Leftover;
  768.     end;
  769.  
  770.  
  771.     function SavePICTFile (fname: str255; vnum: integer; SavingSelection, NewFile: boolean): boolean;
  772.         var
  773.             f, err, i, v: integer;
  774.             ByteCount, PICTSize: LongInt;
  775.             PicH: PicHandle;
  776.             fRect, frect2: rect;
  777.             tPort: GrafPtr;
  778.             TheInfo: FInfo;
  779.             SaveInfoRec: PicInfo;
  780.             HeaderSaved: boolean;
  781.  
  782.         procedure Abort;
  783.         begin
  784.             err := fsclose(f);
  785.             if NewFile then
  786.                 err := FSDelete(fname, vnum);
  787.             DisposHandle(handle(PicH));
  788.             exit(SavePICTFile)
  789.         end;
  790.  
  791.     begin
  792.         with info^ do begin
  793.                 if OpPending then
  794.                     KillRoi;
  795.                 SavePICTFile := false;
  796.                 ShowWatch;
  797.                 GetPort(tPort);
  798.                 if SavingSelection then
  799.                     fRect := RoiRect
  800.                 else
  801.                     SetRect(fRect, 0, 0, PixelsPerLine, nlines);
  802.                 with frect do
  803.                     SetRect(frect2, 0, 0, right - left, bottom - top);
  804.                 with osPort^ do begin
  805.                         SetPort(GrafPtr(osPort));
  806.                         pmForeColor(BlackIndex);
  807.                         pmBackColor(WhiteIndex);
  808.                         if OldSystem then begin  {Work around for Palette Manager bug in Systems before 6.0.5.}
  809.                                 RGBForeColor(BlackRGB);
  810.                                 RGBBackColor(WhiteRGB);
  811.                             end;
  812.                         ClipRect(PicRect);
  813.                         LoadLUT(cTable);  {Restore look-up table in case it has changed.}
  814.                         PicH := OpenPicture(fRect2);
  815.                         hlock(handle(PortPixMap));
  816.                         CopyBits(BitMapHandle(PortPixMap)^^, BitMapHandle(PortPixMap)^^, frect, frect2, SrcCopy, nil);
  817.                         hunlock(handle(PortPixMap));
  818.                         ClosePicture;
  819.                         pmForeColor(ForegroundIndex);
  820.                         pmBackColor(BackgroundIndex);
  821.                     end;
  822.                 SetPort(tPort);
  823.                 PICTSize := GetHandleSize(handle(PicH));
  824.                 if PICTSize <= 10 then begin
  825.                         PutMessage('Sorry, but there is not enough memory available to save this PICT file. Try closing some windows, or save as TIFF.');
  826.                         if NewFile then
  827.                             err := FSDelete(fname, vnum);
  828.                         DisposHandle(handle(PicH));
  829.                         exit(SavePICTFile)
  830.                     end;
  831.                 err := fsopen(fname, vnum, f);
  832.                 err := SetFPos(f, FSFromStart, 0);
  833.                 SaveInfoRec := Info^;
  834.                 if (LutMode = GrayScale) or (LutMode = CustomGrayScale) then begin
  835.                         nColors := 256;
  836.                         ColorStart := 0;
  837.                         ColorEnd := 255;
  838.                         LUTMode := Grayscale;
  839.                         IdentityFunction := true;
  840.                     end;
  841.                 HeaderSaved := SaveHeader(f, 0, 0, vnum, fname, SavingSelection, false) = 0;
  842.                 Info^ := SaveInfoRec;
  843.                 if not HeaderSaved then
  844.                     abort;
  845.                 err := fswrite(f, PICTSize, pointer(PicH^));
  846.                 if CheckIO(err) <> 0 then
  847.                     abort;
  848.                 DisposHandle(handle(PicH));
  849.                 ByteCount := PICTSize + HeaderSize;
  850.                 err := SetEOF(f, ByteCount);
  851.                 err := fsclose(f);
  852.                 err := GetFInfo(fname, vnum, TheInfo);
  853.                 if TheInfo.fdCreator <> 'Imag' then begin
  854.                         TheInfo.fdCreator := 'Imag';
  855.                         err := SetFInfo(fname, vnum, TheInfo);
  856.                     end;
  857.                 if TheInfo.fdType <> 'PICT' then begin
  858.                         TheInfo.fdType := 'PICT';
  859.                         err := SetFInfo(fname, vnum, TheInfo);
  860.                     end;
  861.                 err := FlushVol(nil, vnum);
  862.                 if not SavingSelection then begin
  863.                         if (PictureType <> BlankField) and (PictureType <> FrameGrabberType) and (PictureType <> ScionType) and (PictureType <> NullPicture) then begin
  864.                                 PictureType := PictFile;
  865.                                 title := fname;
  866.                                 UpdateTitleBar;
  867.                                 vref := vnum;
  868.                                 revertable := true;
  869.                             end;
  870.                         Changes := false;
  871.                     end;
  872.             end; {with}
  873.         SavePICTFile := true;
  874.     end;
  875.  
  876.  
  877.     procedure SaveAsPICT (fname: str255; RefNum: integer; SavingSelection: boolean);
  878.         var
  879.             f, err, i: integer;
  880.             where: Point;
  881.             TheInfo: FInfo;
  882.             replacing, ok: boolean;
  883.             name: str255;
  884.     begin
  885.         err := GetFInfo(fname, RefNum, TheInfo);
  886.         case err of
  887.             NoErr: 
  888.                 with TheInfo do begin
  889.                         if (fdType <> 'TIFF') and (fdType <> 'PICT') and (fdType <> 'IPIC') then begin
  890.                                 TypeMismatch(fname);
  891.                                 exit(SaveAsPICT)
  892.                             end;
  893.                         replacing := true;
  894.                     end;
  895.             FNFerr:  begin
  896.                     err := create(fname, RefNum, 'Imag', 'PICT');
  897.                     if CheckIO(err) <> 0 then
  898.                         exit(SaveAsPICT);
  899.                     replacing := false;
  900.                 end;
  901.             otherwise
  902.                 if CheckIO(err) <> 0 then
  903.                     exit(SaveAsPICT);
  904.         end;
  905.         ok := SavePICTFile(fname, RefNum, SavingSelection, not Replacing);
  906.         if ok then
  907.             with info^ do
  908.                 UpdateWindowsMenuItem(PixMapSize, title, PicNum);
  909.         with info^ do
  910.             if SavingSelection and replacing and (PictureType <> BlankField) and (PictureType <> FrameGrabberType) and (PictureType <> ScionType) then
  911.                 PictureType := Leftover;
  912.     end;
  913.  
  914.  
  915.     procedure SaveSelection (fname: str255; RefNum: integer; SaveAsSameType: boolean);
  916.         var
  917.             slines, spixelsPerLine: integer;
  918.     begin
  919.         if NoSelection or NotRectangular or NotInBounds then
  920.             exit(SaveSelection);
  921.         if OpPending then
  922.             KillRoi;
  923.         with info^ do begin
  924.                 with RoiRect do begin
  925.                         sPixelsPerLine := right - left;
  926.                         if odd(sPixelsPerLine) and (left + sPixelsPerLine < PicRect.right) and (SaveAsWhat <> asRawData) then
  927.                             sPixelsPerLine := sPixelsPerLine + 1;
  928.                         slines := bottom - top;
  929.                     end;
  930.                 if (PictureType = PictFile) and SaveAsSameType and (SaveAsWhat <> asRawData) then
  931.                     SaveAsPICT(fname, RefNum, true)
  932.                 else
  933.                     SaveAsTIFF(fname, RefNum, sLines, sPixelsPerLine, true);
  934.             end;
  935.     end;
  936.  
  937.  
  938.     procedure SaveAsText (fname: str255; RefNum: integer);
  939.         var
  940.             err, f: integer;
  941.             TheInfo: FInfo;
  942.             ByteCount: LongInt;
  943.     begin
  944.         err := GetFInfo(fname, RefNum, TheInfo);
  945.         case err of
  946.             NoErr: 
  947.                 if TheInfo.fdType <> 'TEXT' then begin
  948.                         TypeMismatch(fname);
  949.                         exit(SaveAsText)
  950.                     end;
  951.             FNFerr:  begin
  952.                     err := create(fname, RefNum, TextCreator, 'TEXT');
  953.                     if CheckIO(err) <> 0 then
  954.                         exit(SaveAsText);
  955.                 end;
  956.             otherwise
  957.                 if CheckIO(err) <> 0 then
  958.                     exit(SaveAsTExt)
  959.         end;
  960.         ShowWatch;
  961.         err := fsopen(fname, RefNum, f);
  962.         if CheckIO(err) <> 0 then
  963.             exit(SaveAsText);
  964.         ByteCount := TextBufSize;
  965.         err := fswrite(f, ByteCount, ptr(TextBufP));
  966.         if CheckIO(err) <> 0 then
  967.             exit(SaveAsText);
  968.         err := SetEof(f, ByteCount);
  969.         err := fsclose(f);
  970.         err := FlushVol(nil, RefNum);
  971.         if WhatsOnClip = TextOnClip then
  972.             WhatsOnClip := NothingOnClip;
  973.     end;
  974.  
  975.  
  976.     procedure SaveAsPICS (fname: str255; fRefNum: integer);
  977.         const
  978.             rErr = 'Error Saving PICS file.';
  979.         var
  980.             err: OSErr;
  981.             TheInfo: FInfo;
  982.             replacing: boolean;
  983.             rRefNum, i, SaveCS: integer;
  984.             frect: rect;
  985.             PicH: array[1..MaxSlices] of PicHandle;
  986.             MinFreeRequired: LongInt;
  987.     begin
  988.         with info^, Info^.StackInfo^ do begin
  989.                 if StackInfo = nil then begin
  990.                         PutMessage('Only Stacks can be saved in PICS format.');
  991.                         SaveAsWhat := asTiff;
  992.                         exit(SaveAsPICS);
  993.                     end;
  994.                 if ImageSize > MinFree then
  995.                     MinFreeRequired := ImageSize
  996.                 else
  997.                     MinFreeRequired := MinFree;
  998.                 if MaxBlock < MinFreeRequired then begin
  999.                         PutMessage('Not enough memory available to save in PICS format.');
  1000.                         exit(SaveAsPICS);
  1001.                     end;
  1002.                 err := GetFInfo(fname, fRefNum, TheInfo);
  1003.                 if err = NoErr then
  1004.                     with TheInfo do begin
  1005.                             if (fdType <> 'TIFF') and (fdType <> 'PICT') and (fdType <> 'PICS') then begin
  1006.                                     TypeMismatch(fname);
  1007.                                     exit(SaveAsPICS)
  1008.                                 end;
  1009.                             err := FSDelete(fname, fRefNum);
  1010.                         end;
  1011.                 ShowWatch;
  1012.                 err := SetVol(nil, fRefNum);
  1013.                 CreateResFile(fname);
  1014.                 if ResError <> NoErr then
  1015.                     exit(SaveAsPICS);
  1016.                 rRefNum := OpenResFile(fname);
  1017.                 SaveCS := CurrentSlice;
  1018.                 SetPort(GrafPtr(osPort));
  1019.                 with PicRect do
  1020.                     SetRect(frect, 0, 0, right - left, bottom - top);
  1021.                 ClipRect(frect);
  1022.                 LoadLUT(ctable);
  1023.                 pmForeColor(BlackIndex);
  1024.                 pmBackColor(WhiteIndex);
  1025.                 if OldSystem then begin
  1026.                         RGBForeColor(BlackRGB);
  1027.                         RGBBackColor(WhiteRGB);
  1028.                     end;
  1029.                 for i := 1 to nSlices do begin
  1030.                         CurrentSlice := i;
  1031.                         SelectSlice(CurrentSlice);
  1032.                         UpdateTitleBar;
  1033.                         PicH[i] := OpenPicture(frect);
  1034.                         with osPort^ do begin
  1035.                                 hlock(handle(portPixMap));
  1036.                                 CopyBits(BitMapHandle(portPixMap)^^, BitMapHandle(portPixMap)^^, PicRect, frect, SrcCopy, nil);
  1037.                                 hunlock(handle(portPixMap));
  1038.                             end;
  1039.                         ClosePicture;
  1040.                         if (PicH[i] = nil) or ((PicH[i] <> nil) and (GetHandleSize(handle(PicH[i])) <= 10)) then begin
  1041.                                 PutMessage(rErr);
  1042.                                 leave;
  1043.                             end;
  1044.                         AddResource(handle(PicH[i]), 'PICT', i - 1 + 128, '');
  1045.                         if ResError <> NoErr then begin
  1046.                                 PutMessage(rErr);
  1047.                                 leave;
  1048.                             end;
  1049.                         WriteResource(handle(PicH[i]));
  1050.                         ReleaseResource(handle(PicH[i]));
  1051.                         if ResError <> NoErr then begin
  1052.                                 PutMessage(rErr);
  1053.                                 leave;
  1054.                             end;
  1055.                     end; {for}
  1056.                 CurrentSlice := SaveCS;
  1057.                 SelectSlice(CurrentSlice);
  1058.                 title := fname;
  1059.                 PictureType := PicsFile;
  1060.                 UpdateTitleBar;
  1061.                 CloseResFile(rRefNum);
  1062.                 if ResError <> NoErr then
  1063.                     PutMessage(rErr);
  1064.                 err := GetFInfo(fname, fRefNum, TheInfo);
  1065.                 TheInfo.fdType := 'PICS';
  1066.                 TheInfo.fdCreator := 'Imag';
  1067.                 err := SetFInfo(fname, fRefNum, TheInfo);
  1068.                 err := FlushVol(nil, fRefNum);
  1069.                 UpdateWindowsMenuItem(PixMapSize, title, PicNum);
  1070.                 pmForeColor(ForegroundIndex);
  1071.                 pmBackColor(BackgroundIndex);
  1072.             end; {with}
  1073.     end;
  1074.  
  1075.  
  1076.     function SuggestedName: str255;
  1077.         var
  1078.             name: str255;
  1079.     begin
  1080.         case SaveAsWhat of
  1081.             asTiff, asPict, asMacPaint, asRawData, asPICS:  begin
  1082.                     name := info^.title;
  1083.                     if name = 'Camera' then
  1084.                         name := 'Untitled';
  1085.                     SuggestedName := name;
  1086.                 end;
  1087.             AsPalette: 
  1088.                 SuggestedName := 'Palette';
  1089.             AsOutline: 
  1090.                 SuggestedName := 'Outline';
  1091.         end;
  1092.     end;
  1093.  
  1094.  
  1095.     function SaveAsHook (item: integer; theDialog: DialogPtr): integer;
  1096.         const
  1097.             EditTextID = 7;
  1098.             TiffID = 9;
  1099.             OutlineID = 14;
  1100.         var
  1101.             i: integer;
  1102.             fname: str255;
  1103.             NameEdited: boolean;
  1104.     begin
  1105.         if item = -1 then {Initialize}
  1106.             SetDialogItem(theDialog, TiffID + ord(SaveAsWhat), 1);
  1107.         fname := GetDString(theDialog, EditTextID);
  1108.         NameEdited := fname <> SuggestedName;
  1109.         if (item >= TiffID) and (item <= OutlineID) then begin
  1110.                 SaveAsWhat := SaveAsWhatType(item - TiffID);
  1111.                 if not NameEdited then begin
  1112.                         SetDString(theDialog, EditTextID, SuggestedName);
  1113.                         SelIText(theDialog, EditTextID, 0, 32767);
  1114.                     end;
  1115.                 for i := TiffID to OutlineID do
  1116.                     SetDialogItem(theDialog, i, 0);
  1117.                 SetDialogItem(theDialog, item, 1);
  1118.             end;
  1119.         SaveAsHook := item;
  1120.     end;
  1121.  
  1122.  
  1123.     procedure SaveAs (name: str255; RefNum: integer);
  1124.         const
  1125.             CustomDialogID = 60;
  1126.         var
  1127.             where: Point;
  1128.             reply: SFReply;
  1129.             isSelection: boolean;
  1130.             kind: integer;
  1131.     begin
  1132.         with info^ do begin
  1133.                 if SaveAllState = SaveAllStage2 then begin
  1134.                         name := title;
  1135.                         RefNum := SaveRefNum;
  1136.                         if SaveAsWhat = AsPalette then
  1137.                             SaveAsWhat := AsTiff;
  1138.                     end
  1139.                 else if (name = '') or (RefNum = 0) then begin
  1140.                         where.v := 50;
  1141.                         where.h := 50;
  1142.                         if (StackInfo = nil) and (SaveAsWhat = asPICS) then
  1143.                             SaveAsWhat := asTIFF;
  1144.                         if (StackInfo <> nil) and ((SaveAsWhat = asPICT) or (SaveAsWhat = asMacPaint)) then
  1145.                             SaveAsWhat := asTIFF;
  1146.                         if name = '' then
  1147.                             name := SuggestedName;
  1148.                         SFPPutFile(Where, 'Save as?', name, @SaveAsHook, reply, CustomDialogID, nil);
  1149.                         if not reply.good then begin
  1150.                                 SaveAllState := NoSaveAll;
  1151.                                 macro := false;
  1152.                                 exit(SaveAs);
  1153.                             end;
  1154.                         with reply do begin
  1155.                                 name := fname;
  1156.                                 RefNum := vRefNum;
  1157.                                 DefaultRefNum := RefNum;
  1158.                             end;
  1159.                     end;
  1160.                 if StackInfo <> nil then begin
  1161.                         if SaveAsWhat <> asOutline then
  1162.                             KillRoi;
  1163.                         SaveAllState := NoSaveAll;
  1164.                         if not ((SaveAsWhat = asTIFF) or (SaveAsWhat = asPICS) or (SaveAsWhat = asPalette) or (SaveAsWhat = asOutline)) then begin
  1165.                                 PutMessage('Stacks can only be saved in TIFF or PICS format.');
  1166.                                 SaveAsWhat := asTIFF;
  1167.                                 exit(SaveAs);
  1168.                             end;
  1169.                     end;
  1170.                 isSelection := RoiShowing and (RoiType = RectRoi);
  1171.                 if SaveAllState = SaveAllStage1 then begin
  1172.                         SaveRefNum := RefNum;
  1173.                         SaveAllState := SaveAllStage2;
  1174.                     end;
  1175.                 case SaveAsWhat of
  1176.                     asTiff, asRawData: 
  1177.                         if isSelection then
  1178.                             SaveSelection(name, RefNum, false)
  1179.                         else
  1180.                             SaveAsTIFF(name, RefNum, 0, 0, false);
  1181.                     asPict: 
  1182.                         if isSelection then
  1183.                             SaveAsPICT(name, RefNum, true)
  1184.                         else
  1185.                             SaveAsPICT(name, RefNum, false);
  1186.                     asMacPaint: 
  1187.                         SaveAsMacPaint(name, RefNum);
  1188.                     asPICS: 
  1189.                         SaveAsPICS(name, RefNum);
  1190.                     AsPalette: 
  1191.                         SaveColorTable(name, RefNum);
  1192.                     AsOutline: 
  1193.                         SaveOutline(name, RefNum);
  1194.                 end; {case}
  1195.                 if (SaveAsWhat = asRawData) and (SaveAllState <> SaveAllStage2) then
  1196.                     SaveAsWhat := asTIFF;
  1197.             end; {with}
  1198.     end;
  1199.  
  1200.  
  1201.     procedure SaveFile;
  1202.         var
  1203.             fname: str255;
  1204.             size: LongInt;
  1205.             ok: boolean;
  1206.     begin
  1207.         if CurrentWindow = ResultsKind then begin
  1208.                 Export('', 0);
  1209.                 exit(SaveFile);
  1210.             end;
  1211.         if CurrentWindow = TextKind then begin
  1212.                 SaveText;
  1213.                 exit(SaveFile);
  1214.             end;
  1215.         if OpPending then
  1216.             KillRoi;
  1217.         with Info^ do begin
  1218.                 fname := title;
  1219.                 size := 0;
  1220.                 if PictureType = TiffFile then
  1221.                     ok := SaveTiffFile(fname, vref, 0, 0, false)
  1222.                 else if PictureType = PictFile then
  1223.                     ok := SavePICTFile(fname, vref, false, false)
  1224.                 else
  1225.                     SaveAs('', 0);
  1226.             end;
  1227.     end;
  1228.  
  1229.  
  1230.     function SaveChanges: integer;
  1231.         const
  1232.             yesID = 1;
  1233.             noID = 2;
  1234.             cancelID = 3;
  1235.         var
  1236.             id: integer;
  1237.             reply: SFReply;
  1238.     begin
  1239.         id := 0;
  1240.         if info^.changes then
  1241.             with info^ do begin
  1242.                     if CommandPeriod or MakingStack or (macro and ((MacroCommand = DisposeC) or (MacroCommand = DisposeAllC))) then begin
  1243.                             SaveChanges := ok;
  1244.                             exit(SaveChanges);
  1245.                         end;
  1246.                     ParamText(title, '', '', '');
  1247.                     InitCursor;
  1248.                     id := alert(600, nil);
  1249.                     if id = yesID then begin
  1250.                             SaveFile;
  1251.                             InitCursor;
  1252.                         end; {if yes}
  1253.                 end; {if changes}
  1254.         if (id = cancelID) or ((id = yesID) and (info^.changes)) then
  1255.             SaveChanges := cancel
  1256.         else
  1257.             SaveChanges := ok;
  1258.     end;
  1259.  
  1260.  
  1261.     function CloseAWindow (WhichWindow: WindowPtr): integer;
  1262.         var
  1263.             i, kind, n: integer;
  1264.             TempInfo: InfoPtr;
  1265.             TempTextInfo: TextInfoPtr;
  1266.             SizeStr, str: str255;
  1267.             wp: ^WindowPtr;
  1268.             pcrect: rect;
  1269.     begin
  1270.         if WhichWindow = nil then
  1271.             exit(CloseAWindow);
  1272.         kind := WindowPeek(WhichWindow)^.WindowKind;
  1273.         CloseAWindow := ok;
  1274.         if WhichWindow = VideoControl then begin
  1275.                 DisposDialog(VideoControl);
  1276.                 VideoControl := nil;
  1277.                 exit(CloseAWindow);
  1278.             end;
  1279.         case kind of
  1280.             PicKind:  begin
  1281.                     Info := pointer(WindowPeek(WhichWindow)^.RefCon);
  1282.                     with Info^ do begin
  1283.                             if PicNum = 0 then begin
  1284.                                     beep;
  1285.                                     exit(CloseAWindow);
  1286.                                 end;
  1287.                             if SaveChanges = cancel then begin
  1288.                                     CloseAWindow := cancel;
  1289.                                     exit(CloseAWindow)
  1290.                                 end;
  1291.                             DelMenuItem(WindowsMenuH, PicNum + WindowsMenuItems + nTextWindows);
  1292.                             for i := PicNum to nPics - 1 do begin
  1293.                                     PicWindow[i] := PicWindow[i + 1];
  1294.                                     TempInfo := pointer(WindowPeek(PicWindow[i])^.RefCon);
  1295.                                     TempInfo^.PicNum := i
  1296.                                 end;
  1297.                             if PictureType = BlankField then
  1298.                                 BlankFieldInfo := nil;
  1299.                             if StackInfo <> nil then begin
  1300.                                     with StackInfo^ do
  1301.                                         for i := 1 to nSlices do
  1302.                                             DisposHandle(PicBaseH[i]);
  1303.                                     DisposPtr(pointer(StackInfo));
  1304.                                 end
  1305.                             else begin
  1306.                                     if not MakingStack then
  1307.                                         DisposHandle(PicBaseHandle);
  1308.                                 end;
  1309.                             DisposeWindow(WhichWindow);
  1310.                             CloseCPort(osPort);
  1311.                             DisposPtr(ptr(osPort));
  1312.                             DisposeRgn(roiRgn);
  1313.                             nPics := nPics - 1;
  1314.                             OpPending := false;
  1315.                             isInsertionPoint := false;
  1316.                             DisposPtr(pointer(Info));
  1317.                             Info := NoInfo;
  1318.                             if (nPics = 0) and (not finished) then
  1319.                                 with info^ do begin
  1320.                                         LoadLUT(info^.cTable);
  1321.                                         if (LutMode = GrayScale) or (LutMode = CustomGrayScale) then
  1322.                                             DrawMap;
  1323.                                     end;
  1324.                             PicLeft := PicLeftBase;
  1325.                             PicTop := PicTopBase;
  1326.                         end;
  1327.                 end; {PicKind}
  1328.             HistoKind:  begin
  1329.                     DisposeWindow(HistoWindow);
  1330.                     HistoWindow := nil;
  1331.                     ContinuousHistogram := false;
  1332.                 end;
  1333.             ProfilePlotKind, CalibrationPlotKind:  begin
  1334.                     DisposeWindow(PlotWindow);
  1335.                     PlotWindow := nil;
  1336.                     KillPicture(PlotPICT);
  1337.                     PlotPICT := nil;
  1338.                 end;
  1339.             ResultsKind:  begin
  1340.                     DisposeWindow(ResultsWindow);
  1341.                     ResultsWindow := nil;
  1342.                     TEDispose(ListTE);
  1343.                 end;
  1344.             TextKind:  begin
  1345.                     TextInfo := TextInfoPtr(WindowPeek(WhichWindow)^.RefCon);
  1346.                     if TextInfo <> nil then
  1347.                         with TextInfo^ do begin
  1348.                                 if SaveTextChanges = cancel then begin
  1349.                                         CloseAWindow := cancel;
  1350.                                         exit(CloseAWindow)
  1351.                                     end;
  1352.                                 DisposeWindow(TextWindowPtr);
  1353.                                 DelMenuItem(WindowsMenuH, WindowsMenuItems - 1 + WindowNum);
  1354.                                 TEDispose(TextTE);
  1355.                                 DisposePtr(ptr(TextInfo));
  1356.                                 TextInfo := nil;
  1357.                                 for i := WindowNum to nTextWindows - 1 do begin
  1358.                                         TextWindow[i] := TextWindow[i + 1];
  1359.                                         TempTextInfo := pointer(WindowPeek(TextWindow[i])^.RefCon);
  1360.                                         TempTextInfo^.WindowNum := i
  1361.                                     end;
  1362.                                 nTextWindows := nTextWindows - 1;
  1363.                             end;
  1364.                 end;
  1365.             PasteControlKind:  begin
  1366.                     GetWindowRect(PasteControl, pcrect);
  1367.                     with pcrect do begin
  1368.                             PasteControlLeft := left;
  1369.                             PasteControlTop := top;
  1370.                         end;
  1371.                     DisposeWindow(PasteControl);
  1372.                     PasteControl := nil;
  1373.                     wp := pointer(GhostWindow);
  1374.                     wp^ := nil;
  1375.                 end;
  1376.             otherwise
  1377.                 ;
  1378.         end; {case}
  1379.     end;
  1380.  
  1381.  
  1382.     procedure DoClose;
  1383.         var
  1384.             ignore: integer;
  1385.             fwptr: WindowPtr;
  1386.             kind: integer;
  1387.     begin
  1388.         fwptr := FrontWindow;
  1389.         if fwptr <> nil then begin
  1390.                 if fwptr = VideoControl then begin
  1391.                         DisposDialog(VideoControl);
  1392.                         VideoControl := nil;
  1393.                         exit(DoClose);
  1394.                     end;
  1395.                 kind := WindowPeek(fwptr)^.WindowKind;
  1396.                 if (kind = PicKind) or (kind = ProfilePlotKind) or (kind = CalibrationPlotKind) or (kind = HistoKind) or (Kind = PasteControlKind) or (Kind = ResultsKind) or (Kind = TextKind) then
  1397.                     ignore := CloseAWindow(fwptr);
  1398.             end;
  1399.     end;
  1400.  
  1401.  
  1402.     procedure Read4BitTIFF (f: integer);
  1403.         var
  1404.             vloc, hloc, i: integer;
  1405.             ByteCount, count: LongInt;
  1406.             err: OSErr;
  1407.             UnpackedLine, PackedLine: LineType;
  1408.     begin
  1409.         with info^ do begin
  1410.                 if PixelsPerLine > MaxLine then
  1411.                     exit(Read4BitTIFF);
  1412.                 ByteCount := (PixelsPerLine + 1) div 2;
  1413.                 for vloc := 0 to nLines - 1 do begin
  1414.                         err := FSRead(f, ByteCount, @PackedLine);
  1415.                         i := 0;
  1416.                         for hloc := 0 to PixelsPerLine - 1 do
  1417.                             if odd(hloc) then begin
  1418.                                     UnpackedLine[hloc] := bsl(band(PackedLine[i], $F), 4);
  1419.                                     i := i + 1;
  1420.                                 end
  1421.                             else
  1422.                                 UnpackedLine[hloc] := band(PackedLine[i], $F0);
  1423.                         PutLine(0, vloc, PixelsPerLine, UnpackedLine);
  1424.                     end;
  1425.             end; {with}
  1426.     end;
  1427.  
  1428.  
  1429.     procedure ReadStackSlices (f, nExtraImages: integer; var table: TiffIFDTable);
  1430.         var
  1431.             i, err, SaveCS: integer;
  1432.             h: handle;
  1433.             DataSize: LongInt;
  1434.     begin
  1435.         ShowMessage(CmdPeriodToStop);
  1436.         with info^ do begin
  1437.                 StackInfo := StackInfoPtr(NewPtr(SizeOf(StackInfoRec)));
  1438.                 if StackInfo = nil then
  1439.                     exit(ReadStackSlices);
  1440.             end;
  1441.         with info^, info^.StackInfo^ do begin
  1442.                 nSlices := nExtraImages + 1;
  1443.                 CurrentSlice := TempStackInfo.CurrentSlice;
  1444.                 if (CurrentSlice < 1) or (CurrentSlice > nSlices) then
  1445.                     CurrentSlice := 1;
  1446.                 SliceSpacing := TempStackInfo.SliceSpacing;
  1447.                 LoopTime := TempStackInfo.LoopTime;
  1448.                 SaveCS := CurrentSlice;
  1449.                 PicBaseH[1] := PicBaseHandle;
  1450.                 revertable := false;
  1451.                 for i := 2 to nSlices do begin
  1452.                         h := NewHandle(PixMapSize);
  1453.                         if h = nil then begin
  1454.                                 nSlices := i - 1;
  1455.                                 leave;
  1456.                             end;
  1457.                         PicBaseH[i] := h;
  1458.                         CurrentSlice := i;
  1459.                         SelectSlice(i);
  1460.                         UpdateTitleBar;
  1461.                         DataSize := ImageSize;
  1462.                         err := SetFPos(f, fsFromStart, table[i - 1].offset);
  1463.                         err := fsread(f, DataSize, h^);
  1464.                         if odd(PixelsPerLine) then
  1465.                             UnpackLines;
  1466.                         if (PictureType = InvertedTIFF) or ((PictureType = Imported) and ImportInvert) then
  1467.                             InvertPic;
  1468.                         UpdatePicWindow;
  1469.                         if CommandPeriod then begin
  1470.                                 beep;
  1471.                                 nSlices := i;
  1472.                                 wait(60);
  1473.                                 leave;
  1474.                             end;
  1475.                     end; {for}
  1476.                 if (MaxBlock < MinFree) and (nSlices > 1) then begin
  1477.                         repeat
  1478.                             DisposHandle(PicBaseH[nSlices]);
  1479.                             nSlices := nSlices - 1;
  1480.                         until (MaxBlock > MinFree) or (nSlices = 1);
  1481.                         PutMessage(concat('Not enough memory to open all ', long2str(nExtraImages + 1), ' slices in the stack.'));
  1482.                     end;
  1483.                 CurrentSlice := SaveCS;
  1484.                 if CurrentSlice > nSlices then
  1485.                     CurrentSlice := 1;
  1486.                 SelectSlice(CurrentSlice);
  1487.                 UpdateTitleBar;
  1488.                 UpdateWindowsMenuItem(PixMapSize * nSlices, title, PicNum);
  1489.             end;
  1490.     end;
  1491.  
  1492.  
  1493.     procedure OpenStack (f: integer);
  1494.         var
  1495.             table: TiffIFDTable;
  1496.             i, nExtraImages: integer;
  1497.             where: LongInt;
  1498.     begin
  1499.         nExtraImages := TempStackInfo.nSlices - 1;
  1500.         with info^ do begin
  1501.                 where := ImageDataOffset;
  1502.                 for i := 1 to nExtraImages do
  1503.                     with table[i] do begin
  1504.                             iWidth := PixelsPerLine;
  1505.                             iHeight := nLines;
  1506.                             where := where + ImageSize;
  1507.                             Offset := where;
  1508.                             invert := false;
  1509.                         end;
  1510.                 ReadStackSlices(f, nExtraImages, table);
  1511.             end;
  1512.     end;
  1513.  
  1514.  
  1515.     procedure OpenExtraTiffImages (f: integer; NextTiffIFD: LongInt);
  1516.         var
  1517.             table: TiffIFDTable;
  1518.             TiffInfo: TiffInfoRec;
  1519.             i, nExtraImages: integer;
  1520.             AllSameSize: boolean;
  1521.     begin
  1522.         nExtraImages := 0;
  1523.         repeat
  1524.             if not OpenTiffDirectory(f, NextTiffIFD, TiffInfo) then
  1525.                 exit(OpenExtraTiffImages);
  1526.             nExtraImages := nExtraImages + 1;
  1527.             with TiffInfo, table[nExtraImages] do begin
  1528.                     iWidth := width;
  1529.                     iHeight := height;
  1530.                     Offset := OffsetToData;
  1531.                     invert := ZeroIsBlack;
  1532.                     NextTiffIFD := NextIFD;
  1533.                 end;
  1534.         until (NextTiffIFD = 0) or (nExtraImages = MaxSlices);
  1535.         AllSameSize := true;
  1536.         with info^ do begin
  1537.                 for i := 1 to nExtraImages do
  1538.                     AllSameSize := AllSameSize and (PixelsPerLine = table[i].iWidth) and (nLines = table[i].iHeight);
  1539.                 if AllSameSize and not odd(PixelsPerLine) then
  1540.                     ReadStackSlices(f, nExtraImages, table);
  1541.             end;
  1542.     end;
  1543.  
  1544.  
  1545.     function OpenFile (fname: str255; vnum: integer): boolean;
  1546.         var
  1547.             ticks, ByteCount, i, DataSize, NextTiffIFD: LongInt;
  1548.             err: OSErr;
  1549.             f: integer;
  1550.             line, pixel: integer;
  1551.             p: ptr;
  1552.             iptr: ptr;
  1553.             SaveInfo: InfoPtr;
  1554.     begin
  1555.         OpenFile := false;
  1556.         ShowWatch;
  1557.         err := fsopen(fname, vNum, f);
  1558.         SaveInfo := Info;
  1559.         iptr := NewPtr(SizeOf(PicInfo));
  1560.         if iptr = nil then begin
  1561.                 PutMemoryAlert;
  1562.                 err := fsclose(f);
  1563.                 exit(OpenFile)
  1564.             end;
  1565.         Info := pointer(iptr);
  1566.         CloneInfo(SaveInfo^, Info^);
  1567.         with Info^ do begin
  1568.                 ColorMapOffset := 0;
  1569.                 if not OpenHeader(f, fname, vnum, NextTiffIFD) then begin
  1570.                         DisposPtr(iptr);
  1571.                         err := fsclose(f);
  1572.                         Info := SaveInfo;
  1573.                         exit(OpenFile)
  1574.                     end;
  1575.                 PicBaseAddr := GetImageMemory(SaveInfo, PicBaseHandle);
  1576.                 if PicBaseAddr = nil then begin
  1577.                         err := fsclose(f);
  1578.                         exit(OpenFile)
  1579.                     end;
  1580.                 MakeNewWindow(fname);
  1581.                 err := SetFPos(f, fsFromStart, ImageDataOffset);
  1582.                 if PictureType = FourBitTIFF then
  1583.                     Read4BitTIFF(f)
  1584.                 else begin
  1585.                         DataSize := LongInt(nlines) * PixelsPerLine;
  1586.                         err := fsread(f, DataSize, PicBaseAddr);
  1587.                         if CheckIO(err) <> NoErr then begin
  1588.                                 err := fsclose(f);
  1589.                                 exit(OpenFile)
  1590.                             end;
  1591.                     end;
  1592.                 if odd(PixelsPerLine) and (PictureType <> FourBitTiff) then
  1593.                     UnpackLines;
  1594.                 if (PictureType = pdp11) or (PictureType = InvertedTIFF) or ((PictureType = Imported) and (ImportInvert or (WhatToImport = ImportMCID))) then
  1595.                     InvertPic;
  1596.                 if PictureType = FourBitTIFF then
  1597.                     PictureType := imported;
  1598.                 vref := vnum;
  1599.                 if PixMapSize > UndoBufSize then
  1600.                     PutWarning;
  1601.                 revertable := true;
  1602.             end; {with}
  1603.         if TempStackInfo.nSlices > 0 then
  1604.             OpenStack(f)
  1605.         else if NextTiffIFD > 0 then
  1606.             OpenExtraTiffImages(f, NextTiffIFD);
  1607.         err := fsclose(f);
  1608.         OpenFile := true;
  1609.     end;
  1610.  
  1611.  
  1612.     procedure ScaleToEightBits (f: integer);
  1613.         type
  1614.             PixelLUTType = packed array[0..65535] of Unsignedbyte;
  1615.             PixelLUTPtr = ^PixelLUTType;
  1616.             IntLineType = array[0..MaxLine] of integer;
  1617.         var
  1618.             line: LineType;
  1619.             i, j, value, LineSize, offset: LongInt;
  1620.             ScaleFactor: extended;
  1621.             hloc, vloc, wwidth, wheight, IntValue, SaveBytesPerRow: integer;
  1622.             PixelLUT: PixelLUTPtr;
  1623.             str1, str2: str255;
  1624.             err: integer;
  1625.             aLine: IntLineType;
  1626.  
  1627.         procedure reset;
  1628.             var
  1629.                 DataSize, SliceOffset: LongInt;
  1630.                 p: ptr;
  1631.         begin
  1632.             with info^ do begin
  1633.                     if StackInfo <> nil then
  1634.                         SliceOffset := ImageSize * 2 * (StackInfo^.CurrentSlice - 1)
  1635.                     else
  1636.                         SliceOffset := 0;
  1637.                     err := SetFPos(f, fsFromStart, ImageDataOffset + SliceOffset);
  1638.                     if DataH <> nil then begin
  1639.                             if offset = -1 then begin
  1640.                                     hlock(DataH);
  1641.                                     DataSize := ImageSize * 2;
  1642.                                     err := fsread(f, DataSize, DataH^);
  1643.                                 end;
  1644.                             offset := 0
  1645.                         end;
  1646.                 end;
  1647.         end;
  1648.  
  1649.         procedure GetIntLine (var line: IntLineType);
  1650.             type
  1651.                 atype = packed array[1..2] of char;
  1652.             var
  1653.                 p: ptr;
  1654.                 a: atype;
  1655.                 c: char;
  1656.                 i: integer;
  1657.         begin
  1658.             with info^ do begin
  1659.                     if DataH <> nil then begin
  1660.                             p := ptr(ord4(DataH^) + offset);
  1661.                             BlockMove(p, @line, LineSize);
  1662.                             offset := offset + LineSize;
  1663.                         end
  1664.                     else
  1665.                         err := fsread(f, LineSize, @line);
  1666.                     if LittleEndian then
  1667.                         for i := 0 to LineSize div 2 - 1 do begin
  1668.                                 a := atype(line[i]);
  1669.                                 c := a[1];
  1670.                                 a[1] := a[2];
  1671.                                 a[2] := c;
  1672.                                 line[i] := integer(a)
  1673.                             end;
  1674.                 end;
  1675.         end;
  1676.  
  1677.     begin
  1678.         with info^ do begin
  1679.                 PixelLUT := PixelLUTPtr(NewPtr(SizeOf(PixelLUTType)));
  1680.                 if PixelLUT = nil then begin
  1681.                         if DataH <> nil then begin
  1682.                                 DisposHandle(DataH);
  1683.                                 DataH := nil
  1684.                             end;
  1685.                         PutMessage('Not enough memory to do 16 to 8-bit scaling.');
  1686.                         macro := false;
  1687.                         exit(ScaleToEightBits);
  1688.                     end;
  1689.                 offset := -1;
  1690.                 reset;
  1691.                 LineSize := PixelsPerLine * 2;
  1692.                 if (AbsoluteMin = 0) and (AbsoluteMax = 0) then begin
  1693.                         AbsoluteMin := 999999;
  1694.                         AbsoluteMax := -999999;
  1695.                         for vloc := 0 to nlines - 1 do begin
  1696.                                 GetIntLine(aLine);
  1697.                                 for hloc := 0 to PixelsPerLine - 1 do begin
  1698.                                         value := aLine[hloc];
  1699.                                         if (DataType = SixteenBitsUnsigned) and (value < 0) then
  1700.                                             value := value + 65536;
  1701.                                         if value > AbsoluteMax then
  1702.                                             AbsoluteMax := value;
  1703.                                         if value < AbsoluteMin then
  1704.                                             AbsoluteMin := value;
  1705.                                     end {for hloc:=}
  1706.                             end;{for vloc := }
  1707.                         if (CurrentMin = 0) and (CurrentMax = 0) then begin
  1708.                                 CurrentMin := AbsoluteMin;
  1709.                                 CurrentMax := AbsoluteMax;
  1710.                             end;
  1711.                         reset;
  1712.                     end;
  1713.                 str1 := concat('min=', long2str(CurrentMin), ' (', long2str(AbsoluteMin), ')', cr, 'max=', long2str(CurrentMax), ' (', long2str(AbsoluteMax), ')');
  1714.                 ScaleFactor := 253.0 / (CurrentMax - CurrentMin);
  1715.                 RealToString(ScaleFactor, 1, 4, str2);
  1716.                 ShowMessage(concat(str1, cr, 'scale factor= ', str2));
  1717.                 j := 0;
  1718.                 for i := CurrentMin to CurrentMax do begin
  1719.                         PixelLUT^[j] := round((i - CurrentMin) * ScaleFactor + 1);
  1720.                         j := j + 1;
  1721.                     end;
  1722.                 for vloc := 0 to nlines - 1 do begin
  1723.                         GetIntLine(aLine);
  1724.                         for hloc := 0 to PixelsPerLine - 1 do begin
  1725.                                 value := aLine[hloc];
  1726.                                 if (DataType = SixteenBitsUnsigned) and (value < 0) then
  1727.                                     value := value + 65536;
  1728.                                 if value < CurrentMin then
  1729.                                     value := CurrentMin;
  1730.                                 if value > CurrentMax then
  1731.                                     value := CurrentMax;
  1732.                                 line[hloc] := PixelLUT^[value - CurrentMin];
  1733.                                 i := i + 1;
  1734.                             end;
  1735.                         PutLine(0, vloc, PixelsPerLine, line);
  1736.                     end;
  1737.                 if DensityCalibrated then begin
  1738.                         fit := StraightLine;
  1739.                         nCoefficients := 2;
  1740.                         coefficient[2] := (CurrentMin - CurrentMax) / 253.0;
  1741.                         coefficient[1] := CurrentMax - coefficient[2];
  1742.                         ZeroClip := false;
  1743.                         UpdateTitleBar;
  1744.                     end
  1745.                 else
  1746.                     DensityCalibrated := false;
  1747.                 DisposPtr(ptr(PixelLUT));
  1748.                 if DataH <> nil then begin
  1749.                         DisposHandle(DataH);
  1750.                         DataH := nil
  1751.                     end;
  1752.             end; {with}
  1753.     end;
  1754.  
  1755.  
  1756.     procedure RescaleToEightBits;
  1757.         var
  1758.             range: LongInt;
  1759.             err: OSErr;
  1760.             f: integer;
  1761.     begin
  1762.         with info^ do begin
  1763.                 ShowWatch;
  1764.                 KillRoi;
  1765.                 DisableDensitySlice;
  1766.                 err := fsopen(title, vref, f);
  1767.                 if CheckIO(err) <> 0 then
  1768.                     exit(RescaleToEightBits);
  1769.                 range := CurrentMax - CurrentMin;
  1770.                 if ColorStart > 0 then
  1771.                     CurrentMax := CurrentMax - round((ColorStart / 255) * range)
  1772.                 else
  1773.                     CurrentMax := AbsoluteMax;
  1774.                 if ColorEnd < 255 then
  1775.                     CurrentMin := CurrentMin + round(((255 - ColorEnd) / 255) * range)
  1776.                 else
  1777.                     CurrentMin := AbsoluteMin;
  1778.                 ScaleToEightBits(f);
  1779.                 err := fsclose(f);
  1780.                 InvertPic;
  1781.                 UpdatePicWindow;
  1782.                 ResetMap;
  1783.                 if DensityCalibrated then
  1784.                     GenerateValues;
  1785.             end;
  1786.     end;
  1787.  
  1788.  
  1789.     procedure Import16BitSlices (f: integer);
  1790.         var
  1791.             i, err: integer;
  1792.             h: handle;
  1793.             DataSize, nImages, MaxImages, FileSize: LongInt;
  1794.     begin
  1795.         with info^ do begin
  1796.                 nImages := ImportCustomSlices;
  1797.                 err := GetEof(f, FileSize);
  1798.                 MaxImages := (FileSize - ImportCustomOffset) div (ImageSize * 2);
  1799.                 if nImages > MaxImages then
  1800.                     nImages := MaxImages;
  1801.                 if nImages < 2 then
  1802.                     exit(Import16BitSlices);
  1803.                 ShowMessage(CmdPeriodToStop);
  1804.                 StackInfo := StackInfoPtr(NewPtr(SizeOf(StackInfoRec)));
  1805.                 if StackInfo = nil then
  1806.                     exit(Import16BitSlices);
  1807.             end; {with}
  1808.         with info^, info^.StackInfo^ do begin
  1809.                 nSlices := nImages;
  1810.                 SliceSpacing := 0.0;
  1811.                 LoopTime := 0.0;
  1812.                 PicBaseH[1] := PicBaseHandle;
  1813.                 revertable := false;
  1814.                 for i := 2 to nSlices do begin
  1815.                         h := NewHandle(PixMapSize);
  1816.                         if h = nil then begin
  1817.                                 nSlices := i - 1;
  1818.                                 leave;
  1819.                             end;
  1820.                         PicBaseH[i] := h;
  1821.                         CurrentSlice := i;
  1822.                         SelectSlice(i);
  1823.                         UpdateTitleBar;
  1824.                         DataSize := ImageSize;
  1825.                         AbsoluteMin := 0;
  1826.                         AbsoluteMax := 0;
  1827.                         CurrentMin := 0;
  1828.                         CurrentMax := 0;
  1829.                         if not ImportAutoScale then begin
  1830.                                 CurrentMin := round(ImportMin);
  1831.                                 CurrentMax := round(ImportMax);
  1832.                                 if ((CurrentMax - CurrentMin) > 65536) or (CurrentMin > CurrentMax) then begin
  1833.                                         CurrentMin := 0;
  1834.                                         CurrentMin := 0;
  1835.                                     end;
  1836.                             end;
  1837.                         ScaleToEightBits(f);
  1838.                         InvertPic;
  1839.                         InvertPic;
  1840.                         UpdatePicWindow;
  1841.                         if CommandPeriod then begin
  1842.                                 beep;
  1843.                                 nSlices := i;
  1844.                                 wait(60);
  1845.                                 leave;
  1846.                             end;
  1847.                     end; {for}
  1848.                 if (MaxBlock < MinFree) and (nSlices > 1) then begin
  1849.                         repeat
  1850.                             DisposHandle(PicBaseH[nSlices]);
  1851.                             nSlices := nSlices - 1;
  1852.                         until (MaxBlock > MinFree) or (nSlices = 1);
  1853.                         PutMessage(concat('Not enough memory to open all ', long2str(nImages), ' slices in the stack.'));
  1854.                     end;
  1855.                 CurrentSlice := 1;
  1856.                 SelectSlice(CurrentSlice);
  1857.                 UpdateTitleBar;
  1858.                 UpdateWindowsMenuItem(PixMapSize * nSlices, title, PicNum);
  1859.             end;
  1860.     end;
  1861.  
  1862.  
  1863.     function Import16BitFile (fname: str255; vnum: integer): boolean;
  1864.         var
  1865.             ticks, ByteCount, i, NextTiffIFD: LongInt;
  1866.             err: OSErr;
  1867.             f: integer;
  1868.             line, pixel: integer;
  1869.     begin
  1870.         Import16BitFile := false;
  1871.         if ImportCustomWidth > MaxLine then
  1872.             exit(Import16BitFile);
  1873.         if not NewPicWindow(fname, ImportCustomWidth, ImportCustomHeight) then
  1874.             exit(Import16BitFile);
  1875.         ShowWatch;
  1876.         err := fsopen(fname, vNum, f);
  1877.         with info^ do begin
  1878.                 PictureType := imported;
  1879.                 ImageDataOffset := ImportCustomOffset;
  1880.                 DataType := ImportCustomDepth;
  1881.                 vref := vnum;
  1882.                 AbsoluteMin := 0;
  1883.                 AbsoluteMax := 0;
  1884.                 CurrentMin := 0;
  1885.                 CurrentMax := 0;
  1886.                 LittleEndian := ImportSwapBytes;
  1887.                 DensityCalibrated := ImportCalibrate;
  1888.                 if not ImportAutoScale then begin
  1889.                         CurrentMin := round(ImportMin);
  1890.                         CurrentMax := round(ImportMax);
  1891.                         if ((CurrentMax - CurrentMin) > 65536) or (CurrentMin > CurrentMax) then begin
  1892.                                 CurrentMin := 0;
  1893.                                 CurrentMin := 0;
  1894.                             end;
  1895.                     end;
  1896.                 DataH := GetBigHandle(PixMapSize * 2);
  1897.                 ScaleToEightBits(f);
  1898.                 if ImportCustomSlices > 1 then
  1899.                     Import16BitSlices(f);
  1900.                 err := fsclose(f);
  1901.                 InvertPic;
  1902.                 if PixMapSize > UndoBufSize then
  1903.                     PutWarning;
  1904.                 revertable := false;
  1905.             end; {with}
  1906.         Import16BitFile := true;
  1907.     end;
  1908.  
  1909.  
  1910.     procedure InitPictBuffer (howBig: LongInt);
  1911.     begin
  1912.         repeat
  1913.             PictBuffer := NewPtr(howBig);
  1914.             if PictBuffer = nil then
  1915.                 howBig := howBig div 2;
  1916.         until PictBuffer <> nil;
  1917.         DisposPtr(PictBuffer);
  1918.         PictBuffer := NewPtr(howBig div 2);
  1919.     end;
  1920.  
  1921.  
  1922.     procedure FillPictBuffer;
  1923.         var
  1924.             count: LongInt;
  1925.             err: OSErr;
  1926.     begin
  1927.         count := GetPtrSize(PictBuffer);
  1928.         if not fitsInPictBuffer then begin
  1929.                 err := FSRead(PictF, count, PictBuffer);
  1930.                 if err <> NoErr then
  1931.                     PictReadErr := true;
  1932.             end;
  1933.         bytesInPictBuffer := count;
  1934.         curPictBufPtr := PictBuffer;
  1935.     end;
  1936.  
  1937.  
  1938.     procedure GetPICTData (dataPtr: Ptr; byteCount: Integer);
  1939.     {Input picture spooler routine taken from Apple's PICTViewer example program.}
  1940.         var
  1941.             count: LongInt;
  1942.             anErr: OSErr;
  1943.     begin
  1944.         count := byteCount;
  1945.         repeat
  1946.             if bytesInPictBuffer >= count then begin
  1947.                     BlockMove(curPictBufPtr, dataPtr, count);
  1948.                     curPictBufPtr := Ptr(Ord4(curPictBufPtr) + count);
  1949.                     bytesInPictBuffer := bytesInPictBuffer - count;
  1950.                     count := 0;
  1951.                 end
  1952.             else begin        {Not enough in buffer}
  1953.                     if bytesInPictBuffer > 0 then begin
  1954.                             BlockMove(curPictBufPtr, dataPtr, bytesInPictBuffer);
  1955.                             dataPtr := Ptr(Ord4(dataPtr) + bytesInPictBuffer);
  1956.                             count := count - bytesInPictBuffer;
  1957.                         end;
  1958.                     FillPictBuffer;
  1959.                 end;
  1960.         until count = 0;
  1961.     end;
  1962.  
  1963.  
  1964.     procedure BitInfo (var srcBits: PixMap; var srcRect, dstRect: rect; mode: integer; maskRgn: rgnHandle);
  1965.         var
  1966.             i, size: integer;
  1967.     begin
  1968.         if BitInfoCount = 0 then begin
  1969.                 PictSrcRect := srcRect;
  1970.                 if srcBits.rowBytes < 0 then
  1971.                     with srcBits.pmTable^^ do begin{Make sure it is a PixMap.}
  1972.                             size := ctSize;
  1973.                             if size > 255 then
  1974.                                 size := 255;
  1975.                             if size > 0 then begin
  1976.                                     BitInfoCount := BitInfoCount + 1;
  1977.                                     if not UseExistingLUT then
  1978.                                         with info^ do begin
  1979.                                                 for i := 0 to size do
  1980.                                                     cTable[i].rgb := ctTable[i].rgb;
  1981.                                                 LutMode := ColorLut;
  1982.                                                 SetupPseudocolor;
  1983.                                             end;
  1984.                                 end;
  1985.                         end; {with}
  1986.             end;
  1987.     end;
  1988.  
  1989.  
  1990.     procedure GetLUTFromPict (thePict: PicHandle);
  1991.   {Refer to "Screen Dump FKEY for Color Picts", February 1988 MacTutor.}
  1992.         type
  1993.             myPicData = record
  1994.                     p: Picture;
  1995.                     ID: integer
  1996.                 end;
  1997.             myPicPtr = ^myPicData;
  1998.             myPicHdl = ^myPicPtr;
  1999.         var
  2000.             tempProcs: CQDProcs;
  2001.             SavePort: GrafPtr;
  2002.             err: osErr;
  2003.             TempPort: CGrafPort;
  2004.             limbo: rect;
  2005.             xscale, yscale: extended;
  2006.     begin
  2007.         GetPort(SavePort);
  2008.         OpenCPort(@TempPort);
  2009.         SetStdCProcs(tempProcs);
  2010.         tempProcs.bitsProc := @BitInfo;
  2011.         tempProcs.getPicProc := @GetPICTData;
  2012.         PictSrcRect := thePict^^.picFrame;
  2013.         BitInfoCount := 0;
  2014.         TempPort.grafProcs := @tempProcs;
  2015.         err := SetFPos(PictF, fsFromStart, 512 + SizeOf(Picture));
  2016.         FillPictBuffer;
  2017.         limbo := thePict^^.picFrame;
  2018.         OffsetRect(limbo, 10000, 10000);
  2019.         if not PictReadErr then
  2020.             DrawPicture(thePict, limbo);
  2021.         CloseCPort(@TempPort);
  2022.         SetPort(SavePort);
  2023.         with info^, PictSrcRect do begin
  2024.                 LoadLUT(cTable);
  2025.                 xScale := (right - left) / PixelsPerLine;
  2026.                 yScale := (bottom - top) / nLines;
  2027.                 if (xScale > 1.0) and ((PixelsPerLine * xScale) <= MaxLine) and ((xScale - yScale) < 0.1) then begin
  2028.                         PixelsPerLine := right - left;
  2029.                         nLines := bottom - top;
  2030.                     end;
  2031.             end; {with}
  2032.     end;
  2033.  
  2034.  
  2035.     function OpenPict;{(fname:str255; vnum:integer; Reverting:boolean):boolean}
  2036.         var
  2037.             err: OSErr;
  2038.             i: integer;
  2039.             iptr: ptr;
  2040.             PictSize, HowBig, NextTiffIFD: LongInt;
  2041.             thePict: PicHandle;
  2042.             tPort: GrafPtr;
  2043.             tempProcs: CQDProcs;
  2044.             SaveProcsPtr: QDProcsPtr;
  2045.             SaveInfo: InfoPtr;
  2046.  
  2047.         procedure Abort;
  2048.         begin
  2049.             if not reverting then begin
  2050.                     DisposPtr(pointer(Info));
  2051.                     Info := SaveInfo;
  2052.                     LoadLUT(info^.cTable);
  2053.                 end;
  2054.             if thePict <> nil then
  2055.                 DisposHandle(handle(thePict));
  2056.             if PictF <> 0 then
  2057.                 err := fsclose(PictF);
  2058.             exit(OpenPict);
  2059.         end;
  2060.  
  2061.     begin
  2062.         PictF := 0;
  2063.         thePict := nil;
  2064.         OpenPict := false;
  2065.         PictReadErr := false;
  2066.         ShowWatch;
  2067.         SaveInfo := Info;
  2068.         err := fsopen(fname, vNum, PictF);
  2069.         if CheckIO(err) <> 0 then
  2070.             Abort;
  2071.         if not Reverting then begin
  2072.                 iptr := NewPtr(SizeOf(PicInfo));
  2073.                 if iptr = nil then begin
  2074.                         PutMemoryAlert;
  2075.                         err := fsclose(PictF);
  2076.                         exit(OpenPict)
  2077.                     end;
  2078.                 Info := pointer(iptr);
  2079.                 CloneInfo(SaveInfo^, Info^);
  2080.             end;
  2081.         with Info^ do begin
  2082.                 err := GetEof(PictF, PictSize);
  2083.                 if CheckIO(err) <> 0 then
  2084.                     Abort;
  2085.                 PictSize := PictSize - 512;
  2086.                 if PictSize <= 0 then
  2087.                     Abort;
  2088.                 WhatToOpen := OpenPICT2;
  2089.                 if not OpenHeader(PictF, fname, vnum, NextTiffIFD) then
  2090.                     Abort;
  2091.                 thePict := PicHandle(NewHandle(SizeOf(Picture)));
  2092.                 if thePict = nil then
  2093.                     Abort;
  2094.                 err := SetFPos(PictF, fsFromStart, 512);
  2095.                 if CheckIO(err) <> 0 then
  2096.                     Abort;
  2097.                 howBig := SizeOf(Picture);
  2098.                 err := FSRead(PictF, howBig, Pointer(thePict^));
  2099.                 if CheckIO(err) <> 0 then
  2100.                     Abort;
  2101.                 with thePict^^.PicFrame do begin
  2102.                         nlines := bottom - top;
  2103.                         PixelsPerLine := right - left;
  2104.                     end;
  2105.          {....}
  2106.                 err := GetEof(PictF, howBig);
  2107.                 howBig := howBig - (512 + SizeOf(Picture));
  2108.                 InitPictBuffer(HowBig * 2);
  2109.                 if GetPtrSize(PictBuffer) >= howBig then begin
  2110.                         err := FSRead(PictF, howBig, PictBuffer);
  2111.                         if CheckIO(err) <> NoErr then begin
  2112.                                 DisposHandle(handle(thePict));
  2113.                                 DisposPtr(PictBuffer);
  2114.                                 err := fsclose(PictF);
  2115.                                 exit(OpenPict)
  2116.                             end;
  2117.                         fitsInPictBuffer := true;
  2118.                     end
  2119.                 else
  2120.                     fitsInPictBuffer := false;
  2121.                 if (LutMode = ColorLut) or (LutMode = CustomGrayscale) or (iVersion = 0) then
  2122.                     GetLUTFromPict(thePict);
  2123.                 if not Reverting then begin
  2124.                         PicBaseAddr := GetImageMemory(SaveInfo, PicBaseHandle);
  2125.                         if PicBaseAddr = nil then begin
  2126.                                 DisposHandle(handle(thePict));
  2127.                                 DisposPtr(PictBuffer);
  2128.                                 err := fsclose(PictF);
  2129.                                 exit(OpenPict)
  2130.                             end;
  2131.                         MakeNewWindow(fname);
  2132.                     end;
  2133.                 if (PixMapSize > UndoBufSize) and (not Reverting) then begin
  2134.                         PutWarning;
  2135.                         ShowWatch;
  2136.                     end;
  2137.                 if isGrayScaleLUT then
  2138.                     ResetGrayMap;
  2139.                 GetPort(tPort);
  2140.                 SetPort(GrafPtr(osPort));
  2141.                 pmForeColor(BlackIndex);
  2142.                 pmBackColor(WhiteIndex);
  2143.                 RGBForeColor(BlackRGB);
  2144.                 RGBBackColor(WhiteRGB);
  2145.                 EraseRect(PicRect);
  2146.                 SaveProcsPtr := pointer(osPort^.grafProcs);
  2147.                 SetStdCProcs(tempProcs);
  2148.                 tempProcs.getPicProc := @GetPICTData;
  2149.                 osPort^.grafProcs := @TempProcs;
  2150.                 err := SetFPos(PictF, fsFromStart, 512 + SizeOf(Picture));
  2151.                 FillPictBuffer;
  2152.                 if not PictReadErr then
  2153.                     DrawPicture(thePict, PicRect);
  2154.                 osPort^.grafProcs := pointer(SaveProcsPtr);
  2155.                 DisposHandle(handle(thePict));
  2156.                 DisposPtr(PictBuffer);
  2157.                 pmForeColor(ForegroundIndex);
  2158.                 pmBackColor(BackgroundIndex);
  2159.                 SetPort(tPort);
  2160.                 vref := vnum;
  2161.                 PictureType := PictFile;
  2162.                 revertable := true;
  2163.             end; {with}
  2164.         err := fsclose(PictF);
  2165.         SetupUndo;
  2166.         if not PictReadErr then
  2167.             OpenPict := true;
  2168.     end;
  2169.  
  2170.  
  2171.     procedure GetCLUT (thePict: PicHandle);
  2172.         type
  2173.             myPicData = record
  2174.                     p: Picture;
  2175.                     ID: integer
  2176.                 end;
  2177.             myPicPtr = ^myPicData;
  2178.             myPicHdl = ^myPicPtr;
  2179.         var
  2180.             tempProcs: CQDProcs;
  2181.             SaveProcsPtr: QDProcsPtr;
  2182.             err: osErr;
  2183.     begin
  2184.         with info^ do begin
  2185.                 SetPort(GrafPtr(osPort));
  2186.                 SaveProcsPtr := pointer(wptr^.grafProcs);
  2187.                 SetStdCProcs(tempProcs);
  2188.                 tempProcs.bitsProc := @BitInfo;
  2189.                 BitInfoCount := 0;
  2190.                 osPort^.grafProcs := @tempProcs;
  2191.                 DrawPicture(thePict, thePict^^.picFrame);
  2192.                 osPort^.grafProcs := pointer(SaveProcsPtr);
  2193.                 LoadLUT(cTable);
  2194.             end;
  2195.     end;
  2196.  
  2197.  
  2198.     function OpenPICS (name: str255; fRefNum: integer): boolean;
  2199.         var
  2200.             RefNum, picID, hOffset, vOffset, nPICS, i: integer;
  2201.             err: OSErr;
  2202.             PicH: PicHandle;
  2203.             h: handle;
  2204.             MemError, Aborted: boolean;
  2205.             FrameRect: rect;
  2206.  
  2207.         procedure Abort;
  2208.         begin
  2209.             CloseResFile(RefNum);
  2210.             exit(OpenPICS);
  2211.         end;
  2212.  
  2213.     begin
  2214.         OpenPics := false;
  2215.         if MaxBlock < MinFree then begin
  2216.                 PutMessage('Insufficient memory to open PICS file.');
  2217.                 exit(OpenPICS);
  2218.             end;
  2219.         ShowWatch;
  2220.         err := SetVol(nil, fRefNum);
  2221.         RefNum := OpenResFile(name);
  2222.         if RefNum = -1 then begin
  2223.                 PutMessage('Unable to open PICS file.');
  2224.                 exit(OpenPICS);
  2225.             end;
  2226.         nPICS := Count1Resources('PICT');
  2227.         if nPICS < 1 then begin
  2228.                 PutMessage('No PICTs found.');
  2229.                 abort;
  2230.             end;
  2231.         PicH := GetPicture(128);
  2232.         if PicH = nil then
  2233.             Abort;
  2234.         FrameRect := PicH^^.PicFrame;
  2235.         with FrameRect do begin
  2236.                 hOffset := left;
  2237.                 vOffset := top;
  2238.                 right := right - hOffset;
  2239.                 bottom := bottom - vOffset;
  2240.                 left := 0;
  2241.                 top := 0;
  2242.             end;
  2243.         with FrameRect do
  2244.             if not NewPicWindow(name, right - left, bottom - top) then
  2245.                 Abort;
  2246.         with info^ do begin
  2247.                 revertable := false;
  2248.                 StackInfo := StackInfoPtr(NewPtr(SizeOf(StackInfoRec)));
  2249.                 if StackInfo = nil then
  2250.                     Abort;
  2251.                 with StackInfo^ do begin
  2252.                         SliceSpacing := 0.0;
  2253.                         LoopTime := 0.0;
  2254.                         nSlices := 1;
  2255.                         CurrentSlice := 1;
  2256.                         PicBaseH[1] := PicBaseHandle;
  2257.                     end;
  2258.             end;
  2259.         if not UseExistingLUT then
  2260.             GetCLUT(picH);
  2261.         with info^, Info^.StackInfo^ do begin
  2262.                 SetPort(GrafPtr(osPort));
  2263.                 pmBackColor(WhiteIndex);
  2264.                 EraseRect(PicRect);
  2265.                 DrawPicture(picH, PicRect);
  2266.                 DisposHandle(handle(picH));
  2267.                 UpdatePicWindow;
  2268.                 picID := 129;
  2269.                 MemError := false;
  2270.                 for i := 2 to nPICS do begin
  2271.                         PicH := GetPicture(picID);
  2272.                         if (PicH = nil) or (ResError <> NoErr) then
  2273.                             Leave;
  2274.                         h := GetBigHandle(PixMapSize);
  2275.                         if h = nil then begin
  2276.                                 if PicH <> nil then
  2277.                                     DisposHandle(handle(picH));
  2278.                                 MemError := true;
  2279.                                 Leave;
  2280.                             end;
  2281.                         nSlices := nSlices + 1;
  2282.                         CurrentSlice := CurrentSlice + 1;
  2283.                         PicBaseH[CurrentSlice] := h;
  2284.                         SelectSlice(CurrentSlice);
  2285.                         FrameRect := PicH^^.PicFrame;
  2286.                         with FrameRect do begin
  2287.                                 right := right - hOffset;
  2288.                                 bottom := bottom - vOffset;
  2289.                                 left := left - hOffset;
  2290.                                 top := top - vOffset;
  2291.                             end;
  2292.                         EraseRect(PicRect);
  2293.                         if not EqualRect(FrameRect, PicRect) then
  2294.                             BlockMove(PicBaseH[CurrentSlice - 1]^, PicBaseH[CurrentSlice]^, PixMapSize);
  2295.                         DrawPicture(picH, FrameRect);
  2296.                         DisposHandle(handle(picH));
  2297.                         UpdatePicWindow;
  2298.                         UpdateTitleBar;
  2299.                         Aborted := CommandPeriod;
  2300.                         if Aborted then begin
  2301.                                 beep;
  2302.                                 wait(60);
  2303.                                 Leave;
  2304.                             end;
  2305.                         picID := picID + 1;
  2306.                     end;
  2307.                 CloseResFile(RefNum);
  2308.                 if MemError then
  2309.                     PutMessage('Not enough memory to open all images in PICS file.');
  2310.                 CurrentSlice := 1;
  2311.                 SelectSlice(CurrentSlice);
  2312.                 PictureType := PicsFile;
  2313.                 Revertable := false;
  2314.                 UpdateTitleBar;
  2315.                 UpdateWindowsMenuItem(PixMapSize * nSlices, title, PicNum);
  2316.                 if not MemError and not Aborted then
  2317.                     OpenPICS := true;
  2318.             end; {with}
  2319.     end;
  2320.  
  2321.  
  2322. {$D-}
  2323.  
  2324.     procedure OpenAll (RefNum: integer);
  2325.       {Opens all appropriate files in a folder.    Original version contributed by Ira Rampil.}
  2326.         var
  2327.             OpenedOK: boolean;
  2328.             index: integer;
  2329.             name: Str255;
  2330.             ftype: OSType;
  2331.             err: OSErr;
  2332.             PB: HParamBlockRec;
  2333.     begin
  2334.         index := 0;
  2335.         while true do begin
  2336.                 index := index + 1;
  2337.                 with PB do begin
  2338.                         ioCompletion := nil;
  2339.                         ioNamePtr := @name;
  2340.                         ioVRefNUm := RefNum;
  2341.                         ioVersNum := 0;
  2342.                         ioFDirIndex := index;
  2343.                         err := PBGetFInfo(@PB, false);
  2344.                         if err = fnfErr then
  2345.                             exit(OpenAll);
  2346.                         ftype := ioFlFndrInfo.fdType;
  2347.                     end;
  2348.                 if ftype = 'IPIC' then begin
  2349.                         WhatToOpen := OpenImage;
  2350.                         if not OpenFile(name, RefNum) then
  2351.                             exit(OpenAll);
  2352.                     end
  2353.                 else if ftype = 'PICT' then begin
  2354.                         if not OpenPICT(name, RefNum, false) then
  2355.                             exit(OpenAll)
  2356.                     end
  2357.                 else if ftype = 'TIFF' then begin
  2358.                         WhatToOpen := OpenTiff;
  2359.                         if not OpenFile(name, RefNum) then
  2360.                             exit(OpenAll);
  2361.                     end
  2362.                 else if ftype = 'PNTG' then
  2363.                     if not OpenMacPaint(name, RefNum) then
  2364.                         exit(OpenAll);
  2365.             end; {while}
  2366.     end;
  2367.  
  2368.  
  2369.     procedure UpdateFileIcons (reply: SFReply);
  2370.       {Changes the creator of all files in the current folder from 'IMAG'(files created by V1.40 and earlier) to 'Imag'.}
  2371.         var
  2372.             OpenedOK: boolean;
  2373.             RefNum, index: integer;
  2374.             name: Str255;
  2375.             ftype, fcreator: OSType;
  2376.             err: OSErr;
  2377.             PB: HParamBlockRec;
  2378.             TheInfo: FInfo;
  2379.             count: integer;
  2380.     begin
  2381.         RefNum := reply.vRefNum;
  2382.         index := 0;
  2383.         count := 0;
  2384.         ShowWatch;
  2385.         while true do begin
  2386.                 index := index + 1;
  2387.                 with PB do begin
  2388.                         ioCompletion := nil;
  2389.                         ioNamePtr := @name;
  2390.                         ioVRefNum := RefNum;
  2391.                         ioVersNum := 0;
  2392.                         ioFDirIndex := index;
  2393.                         err := PBGetFInfo(@PB, false);
  2394.                         if err = fnfErr then
  2395.                             leave;
  2396.                         ftype := ioFlFndrInfo.fdType;
  2397.                         fcreator := ioFlFndrInfo.fdCreator;
  2398.                     end;
  2399.                 if (fCreator = 'IMAG') and ((ftype = 'IPIC') or (ftype = 'PICT') or (ftype = 'TIFF') or (ftype = 'ICOL')) then begin
  2400.                         err := GetFInfo(name, RefNum, TheInfo);
  2401.                         if err <> NoErr then
  2402.                             leave;
  2403.                         TheInfo.fdCreator := 'Imag';
  2404.                         err := SetFInfo(name, RefNum, TheInfo);
  2405.                         if err <> NoErr then
  2406.                             leave;
  2407.                         err := FlushVol(nil, RefNum);
  2408.                         count := count + 1;
  2409.                     end;
  2410.             end; {while}
  2411.         if count = 0 then
  2412.             PutMessage('None of the files in the current folder use the old icons.')
  2413.         else
  2414.             PutMessage(concat('The creator type of ', long2str(count), ' files in the current folder was changed from ''IMAG'' to ''Imag''.'));
  2415.     end;
  2416.  
  2417.  
  2418.     function OpenDialogHook (item: integer; theDialog: DialogPtr): integer;
  2419.         const
  2420.             OpenAllID = 11;
  2421.             KeepLutID = 12;
  2422.             UpdateIconsID = 13;
  2423.         var
  2424.             i: integer;
  2425.     begin
  2426.         if (item = -1) and UseExistingLUT then
  2427.             SetDialogItem(theDialog, KeepLutID, 1);
  2428.         if item = OpenAllID then begin
  2429.                 OpenAllFiles := not OpenAllFiles;
  2430.                 SetDialogItem(theDialog, OpenAllID, ord(OpenAllFiles));
  2431.             end;
  2432.         if item = KeepLutID then begin
  2433.                 UseExistingLUT := not UseExistingLUT;
  2434.                 SetDialogItem(theDialog, KeepLutID, ord(UseExistingLut));
  2435.             end;
  2436.         if item = UpdateIconsID then begin
  2437.                 UpdateIcons := not UpdateIcons;
  2438.                 SetDialogItem(theDialog, UpdateIconsID, ord(UpdateIcons));
  2439.             end;
  2440.         OpenDialogHook := item;
  2441.     end;
  2442.  
  2443.  
  2444.     function DoOpen (FileName: str255; RefNum: integer): boolean;
  2445.         const
  2446.             MyDialogID = 70;
  2447.         var
  2448.             where: Point;
  2449.             reply: SFReply;
  2450.             b: boolean;
  2451.             sfPtr: ^SFTypeList;
  2452.             TypeList: array[0..10] of OSType;
  2453.             FileType: OSType;
  2454.             OKToContinue: boolean;
  2455.             FinderInfo: FInfo;
  2456.             err: OSErr;
  2457.     begin
  2458.         KillOperation;
  2459.         DisableDensitySlice;
  2460.         OpenAllFiles := false;
  2461.         UseExistingLUT := false;
  2462.         UpdateIcons := false;
  2463.         OKToContinue := false;
  2464.         if FileName = '' then begin
  2465.                 where.v := 50;
  2466.                 where.h := 50;
  2467.                 typeList[0] := 'IPIC';
  2468.                 typeList[1] := 'PICT';
  2469.                 typeList[2] := 'TIFF';
  2470.                 typeList[3] := 'ICOL';   {Color Tables}
  2471.                 typeList[4] := 'PX05'; {PixelPaint LUT}
  2472.                 typeList[5] := 'CLUT';  {Klutz LUT}
  2473.                 typeList[6] := 'drwC';  {Canvas LUT}
  2474.                 typeList[7] := 'PNTG';  {MacPaint}
  2475.                 typeList[8] := 'PICS';
  2476.                 typeList[9] := 'Iout';    {Outlines}
  2477.                 typeList[10] := 'TEXT';
  2478.                 sfPtr := @TypeList;
  2479.                 SFPGetFile(Where, '', nil, 11, sfPtr^, @OpenDialogHook, reply, MyDialogID, nil);
  2480.                 if reply.good then
  2481.                     with reply do begin
  2482.                             FileName := fname;
  2483.                             FileType := ftype;
  2484.                             RefNum := vRefNum;
  2485.                             DefaultRefNum := RefNum;
  2486.                             DefaultFileName := fname;
  2487.                             OKToContinue := true;
  2488.                         end;
  2489.                 if reply.good and UpdateIcons then begin
  2490.                         UpdateFileIcons(reply);
  2491.                         exit(DoOpen);
  2492.                     end;
  2493.                 if reply.good and OpenAllFiles then begin
  2494.                         OpenAll(RefNum);
  2495.                         exit(DoOpen);
  2496.                     end;
  2497.             end
  2498.         else begin
  2499.                 err := GetFInfo(FileName, RefNum, FinderInfo);
  2500.                 FileType := FinderInfo.fdType;
  2501.                 OKToContinue := true;
  2502.             end;
  2503.         DoOpen := OKToContinue;
  2504.         if OKToContinue then begin
  2505.                 if FileType = 'IPIC' then begin
  2506.                         WhatToOpen := OpenImage;
  2507.                         b := OpenFile(FileName, RefNum)
  2508.                     end
  2509.                 else if FileType = 'PICT' then begin
  2510.                         b := OpenPICT(FileName, RefNum, false)
  2511.                     end
  2512.                 else if FileType = 'TIFF' then begin
  2513.                         WhatToOpen := OpenTIFF;
  2514.                         b := OpenFile(FileName, RefNum)
  2515.                     end
  2516.                 else if FileType = 'ICOL' then
  2517.                     OpenColorTable(FileName, RefNum)
  2518.                 else if FileType = 'PX05' then
  2519.                     ImportPalette('PX05', FileName, RefNum)
  2520.                 else if FileType = 'CLUT' then
  2521.                     ImportPalette('CLUT', FileName, RefNum)
  2522.                 else if FileType = 'drwC' then
  2523.                     ImportPalette('PX05', FileName, RefNum)
  2524.                 else if FileType = 'PNTG' then
  2525.                     b := OpenMacPaint(FileName, RefNum)
  2526.                 else if FileType = 'PICS' then
  2527.                     b := OpenPICS(FileName, RefNum)
  2528.                 else if FileType = 'Iout' then
  2529.                     OpenOutline(FileName, RefNum)
  2530.                 else if FileType = 'TEXT' then
  2531.                     b := OpenTextFile(FileName, RefNum)
  2532.                 else begin
  2533.                         WhatToOpen := OpenUnknown;
  2534.                         b := OpenFile(FileName, RefNum)
  2535.                     end;
  2536.                 info^.ScaleToFitWindow := false;
  2537.             end;
  2538.     end;
  2539.  
  2540.  
  2541.     procedure ImportAllFiles (RefNum: integer);
  2542.         var
  2543.             OpenedOK: boolean;
  2544.             index: integer;
  2545.             name: Str255;
  2546.             ftype: OSType;
  2547.             err: OSErr;
  2548.             PB: HParamBlockRec;
  2549.     begin
  2550.         index := 0;
  2551.         while true do begin
  2552.                 index := index + 1;
  2553.                 with PB do begin
  2554.                         ioCompletion := nil;
  2555.                         ioNamePtr := @name;
  2556.                         ioVRefNum := RefNum;
  2557.                         ioVersNum := 0;
  2558.                         ioFDirIndex := index;
  2559.                         err := PBGetFInfo(@PB, false);
  2560.                         if err = fnfErr then
  2561.                             exit(ImportAllFiles);
  2562.                         ftype := ioFlFndrInfo.fdType;
  2563.                     end;
  2564.                 if (WhatToOpen = OpenCustom) and (ImportCustomDepth <> EightBits) then begin
  2565.                         if not Import16BitFile(name, RefNum) then
  2566.                             exit(ImportAllFiles);
  2567.                     end
  2568.                 else begin
  2569.                         if not OpenFile(name, RefNum) then
  2570.                             exit(ImportAllFiles);
  2571.                     end;
  2572.                 if CommandPeriod then begin
  2573.                         beep;
  2574.                         exit(ImportAllFiles);
  2575.                     end;
  2576.             end; {while}
  2577.     end;
  2578.  
  2579.  
  2580.     procedure EditImportParameters;
  2581.         const
  2582.             WidthID = 2;
  2583.             HeightID = 3;
  2584.             OffsetID = 4;
  2585.             SlicesID = 5;
  2586.             FixedID = 6;
  2587.             MinID = 7;
  2588.             MaxID = 8;
  2589.         var
  2590.             mylog: DialogPtr;
  2591.             item, fwidth: integer;
  2592.     begin
  2593.         mylog := GetNewDialog(110, nil, pointer(-1));
  2594.         SetDNum(MyLog, WidthID, ImportCustomWidth);
  2595.         SelIText(MyLog, WidthID, 0, 32767);
  2596.         SetDNum(MyLog, HeightID, ImportCustomHeight);
  2597.         SetDNum(MyLog, SlicesID, ImportCustomSlices);
  2598.         SetDNum(MyLog, OffsetID, ImportCustomOffset);
  2599.         SetDialogItem(MyLog, FixedID, ord(not ImportAutoScale));
  2600.         if WhatToImport = ImportText then
  2601.             fwidth := 2
  2602.         else
  2603.             fwidth := 0;
  2604.         SetDReal(MyLog, MinID, ImportMin, fwidth);
  2605.         SetDReal(MyLog, MaxID, ImportMax, fwidth);
  2606.         OutlineButton(MyLog, ok, 16);
  2607.         repeat
  2608.             ModalDialog(nil, item);
  2609.             if item = WidthID then begin
  2610.                     ImportCustomWidth := GetDNum(MyLog, WidthID);
  2611.                     if (ImportCustomWidth < 0) or (ImportCustomWidth > MaxPicSize) then begin
  2612.                             ImportCustomWidth := 512;
  2613.                             SetDNum(MyLog, WidthID, ImportCustomWidth);
  2614.                         end;
  2615.                 end;
  2616.             if item = HeightID then begin
  2617.                     ImportCustomHeight := GetDNum(MyLog, HeightID);
  2618.                     if ImportCustomHeight < 0 then begin
  2619.                             ImportCustomHeight := 512;
  2620.                             SetDNum(MyLog, HeightID, ImportCustomHeight);
  2621.                         end;
  2622.                 end;
  2623.             if item = SlicesID then begin
  2624.                     ImportCustomSlices := GetDNum(MyLog, SlicesID);
  2625.                     if ImportCustomSlices < 0 then begin
  2626.                             ImportCustomSlices := 1;
  2627.                             SetDNum(MyLog, SlicesID, ImportCustomSlices);
  2628.                         end;
  2629.                 end;
  2630.             if item = OffsetID then begin
  2631.                     ImportCustomOffset := GetDNum(MyLog, OffsetID);
  2632.                     if ImportCustomOffset < 0 then begin
  2633.                             ImportCustomOffset := 0;
  2634.                             SetDNum(MyLog, OffsetID, ImportCustomOffset);
  2635.                         end;
  2636.                 end;
  2637.             if item = FixedID then begin
  2638.                     ImportAutoScale := not ImportAutoScale;
  2639.                     SetDialogItem(mylog, FixedID, ord(not ImportAutoScale));
  2640.                 end;
  2641.             if item = MinID then begin
  2642.                     ImportMin := GetDReal(MyLog, MinID);
  2643.                     ImportAutoScale := false;
  2644.                     SetDialogItem(MyLog, FixedID, 1);
  2645.                 end;
  2646.             if item = MaxID then begin
  2647.                     ImportMax := GetDReal(MyLog, MaxID);
  2648.                     ImportAutoScale := false;
  2649.                     SetDialogItem(MyLog, FixedID, 1);
  2650.                 end;
  2651.         until item = ok;
  2652.         DisposDialog(mylog);
  2653.     end;
  2654.  
  2655.  
  2656.     function ImportDialogHook (item: integer; myLog: DialogPtr): integer;
  2657.         const
  2658.             TiffID = 11;
  2659.             McidID = 12;
  2660.             TextID = 13;
  2661.             LutID = 14;
  2662.             CustomID = 15;
  2663.             WidthAndHeightID = 16;
  2664.             OffsetID = 17;
  2665.             EightBitsID = 18;
  2666.             SixteenBitsUnsignedID = 19;
  2667.             SixteenBitsSignedID = 20;
  2668.             SwapBytesID = 21;
  2669.             ImportAllID = 22;
  2670.             EditID = 23;
  2671.             CalibrateID = 24;
  2672.             InvertID = 25;
  2673.         var
  2674.             i: integer;
  2675.  
  2676.         procedure SetRadioButtons1;
  2677.             var
  2678.                 i: integer;
  2679.         begin
  2680.             SetDialogItem(mylog, TiffID, 0);
  2681.             SetDialogItem(mylog, McidID, 0);
  2682.             SetDialogItem(mylog, LutID, 0);
  2683.             SetDialogItem(mylog, TextID, 0);
  2684.             SetDialogItem(mylog, CustomID, 0);
  2685.             case WhatToImport of
  2686.                 ImportTiff: 
  2687.                     SetDialogItem(mylog, TiffID, 1);
  2688.                 ImportMcid: 
  2689.                     SetDialogItem(mylog, McidID, 1);
  2690.                 ImportLUT: 
  2691.                     SetDialogItem(mylog, LutID, 1);
  2692.                 ImportText: 
  2693.                     SetDialogItem(mylog, TextID, 1);
  2694.                 ImportCustom: 
  2695.                     SetDialogItem(mylog, CustomID, 1);
  2696.             end;
  2697.         end;
  2698.  
  2699.         procedure SetRadioButtons2;
  2700.             var
  2701.                 i: integer;
  2702.         begin
  2703.             SetDialogItem(mylog, EightBitsID, 0);
  2704.             SetDialogItem(mylog, SixteenBitsUnsignedID, 0);
  2705.             SetDialogItem(mylog, SixteenBitsSignedID, 0);
  2706.             case ImportCustomDepth of
  2707.                 EightBits: 
  2708.                     SetDialogItem(mylog, EightBitsID, 1);
  2709.                 SixteenBitsUnsigned: 
  2710.                     SetDialogItem(mylog, SixteenBitsUnsignedID, 1);
  2711.                 SixteenBitsSigned: 
  2712.                     SetDialogItem(mylog, SixteenBitsSignedID, 1);
  2713.             end;
  2714.         end;
  2715.  
  2716.         procedure ShowParameters;
  2717.             var
  2718.                 str1, str2, str3: str255;
  2719.         begin
  2720.             NumToString(ImportCustomWidth, str1);
  2721.             NumToString(ImportCustomHeight, str2);
  2722.             NumToString(ImportCustomOffset, str3);
  2723.             ParamText(str1, str2, str3, '');
  2724.         end;
  2725.  
  2726.     begin
  2727.         if item = -1 then begin {Initialize}
  2728.                 SetRadioButtons1;
  2729.                 SetRadioButtons2;
  2730.                 ShowParameters;
  2731.                 SetDialogItem(mylog, SwapBytesID, ord(ImportSwapBytes));
  2732.                 SetDialogItem(mylog, ImportAllID, ord(ImportAll));
  2733.                 SetDialogItem(mylog, InvertID, ord(ImportInvert));
  2734.                 SetDialogItem(mylog, CalibrateID, ord(ImportCalibrate));
  2735.             end;
  2736.         if (item >= TiffID) and (item <= CustomID) then begin
  2737.                 case item of
  2738.                     TiffID: 
  2739.                         WhatToImport := ImportTiff;
  2740.                     McidID: 
  2741.                         WhatToImport := ImportMCID;
  2742.                     LutID: 
  2743.                         WhatToImport := ImportLUT;
  2744.                     TextID: 
  2745.                         WhatToImport := ImportText;
  2746.                     CustomID: 
  2747.                         WhatToImport := ImportCustom;
  2748.                 end;
  2749.                 SetRadioButtons1;
  2750.             end;
  2751.         if item = EditID then begin
  2752.                 EditImportParameters;
  2753.                 WhatToImport := ImportCustom;
  2754.                 SetRadioButtons1;
  2755.                 ShowParameters;
  2756.                 SetDialogItem(mylog, CalibrateID, ord(ImportCalibrate));
  2757.             end;
  2758.         if (item >= EightBitsID) and (item <= SixteenBitsSignedID) then begin
  2759.                 case item of
  2760.                     EightBitsID: 
  2761.                         ImportCustomDepth := EightBits;
  2762.                     SixteenBitsUnsignedID: 
  2763.                         ImportCustomDepth := SixteenBitsUnsigned;
  2764.                     SixteenBitsSignedID: 
  2765.                         ImportCustomDepth := SixteenBitsSigned;
  2766.                 end;
  2767.                 SetRadioButtons2;
  2768.                 WhatToImport := ImportCustom;
  2769.                 SetRadioButtons1;
  2770.             end;
  2771.         if item = SwapBytesID then begin
  2772.                 ImportSwapBytes := not ImportSwapBytes;
  2773.                 SetDialogItem(mylog, SwapBytesID, ord(ImportSwapBytes));
  2774.                 WhatToImport := ImportCustom;
  2775.                 SetRadioButtons1;
  2776.             end;
  2777.         if item = ImportAllID then begin
  2778.                 ImportAll := not ImportAll;
  2779.                 SetDialogItem(mylog, ImportAllID, ord(ImportAll));
  2780.             end;
  2781.         if item = InvertID then begin
  2782.                 ImportInvert := not ImportInvert;
  2783.                 SetDialogItem(mylog, InvertID, ord(ImportInvert));
  2784.             end;
  2785.         if item = CalibrateID then begin
  2786.                 ImportCalibrate := not ImportCalibrate;
  2787.                 SetDialogItem(mylog, CalibrateID, ord(ImportCalibrate));
  2788.                 WhatToImport := ImportCustom;
  2789.                 SetRadioButtons1;
  2790.             end;
  2791.         ImportDialogHook := item;
  2792.     end;
  2793.  
  2794.  
  2795. {$POP}
  2796.  
  2797.  
  2798.     function ImportFile (FileName: str255; RefNum: integer): boolean;
  2799.         const
  2800.             ImportDialogID = 90;
  2801.         var
  2802.             where: Point;
  2803.             typeList: SFTypeList;
  2804.             reply: SFReply;
  2805.             b, ImportingTIFF: boolean;
  2806.     begin
  2807.         ImportFile := true;
  2808.         DisableDensitySlice;
  2809.         if not macro then
  2810.             ImportAll := false;
  2811.         if FileName = '' then begin
  2812.                 where.v := 50;
  2813.                 where.h := 50;
  2814.                 SFPGetFile(Where, '', nil, -1, typeList, @ImportDialogHook, reply, ImportDialogID, nil);
  2815.                 if not reply.good then begin
  2816.                         ImportFile := false;
  2817.                         exit(ImportFile);
  2818.                     end;
  2819.                 with reply do begin
  2820.                         FileName := fname;
  2821.                         RefNum := vRefNum;
  2822.                         DefaultRefNum := RefNum;
  2823.                         DefaultFileName := fname;
  2824.                     end;
  2825.             end;
  2826.         ImportingTIFF := WhatToImport = ImportTiff;
  2827.         if ImportingTIFF then
  2828.             if not GetTIFFParameters(FileName, RefNum) then
  2829.                 exit(ImportFile);
  2830.         case WhatToImport of
  2831.             ImportMCID: 
  2832.                 WhatToOpen := OpenImported;
  2833.             ImportCustom:  begin
  2834.                     if (ImportCustomDepth <> EightBits) and (ImportCustomWidth > MaxLine) then begin
  2835.                             PutMessage(concat('Maximum width of imported 16-bit images is ', long2str(MaxLine), '.'));
  2836.                             exit(ImportFile);
  2837.                         end;
  2838.                     WhatToOpen := OpenCustom;
  2839.                 end;
  2840.             ImportLUT:  begin
  2841.                     DoImportLut(FileName, RefNum);
  2842.                     exit(ImportFile);
  2843.                 end;
  2844.             ImportText:  begin
  2845.                     ImportFile := ImportTextFile(FileName, RefNum);
  2846.                     exit(ImportFile);
  2847.                 end;
  2848.         end;
  2849.         if ImportAll then
  2850.             ImportAllFiles(RefNum)
  2851.         else if (WhatToOpen = OpenCustom) and (ImportCustomDepth <> EightBits) then
  2852.             b := Import16BitFile(FileName, RefNum)
  2853.         else
  2854.             b := OpenFile(FileName, RefNum);
  2855.         if ImportingTIFF then
  2856.             WhatToImport := ImportTiff;
  2857.     end;
  2858.  
  2859.  
  2860.     procedure RevertToSaved;
  2861.         var
  2862.             fname: str255;
  2863.             err, f: integer;
  2864.             ok: boolean;
  2865.     begin
  2866.         if OpPending then
  2867.             KillRoi;
  2868.         DisableDensitySlice;
  2869.         with Info^ do begin
  2870.                 fname := title;
  2871.                 SetPort(wptr);
  2872.                 if PictureType = PICTFile then begin
  2873.                         ok := OpenPICT(fname, vref, true);
  2874.                         UpdatePicWindow;
  2875.                     end
  2876.                 else begin
  2877.                         ShowWatch;
  2878.                         err := fsopen(fname, vref, f);
  2879.                         ok := true;
  2880.                         if HeaderOffset <> -1 then
  2881.                             ok := OpenImageHeader(f, fname, vref);
  2882.                         if ok then begin
  2883.                                 err := SetFPos(f, fsFromStart, ImageDataOffset);
  2884.                                 err := fsread(f, ImageSize, PicBaseAddr);
  2885.                                 with info^ do
  2886.                                     if (PictureType = PDP11) or (PictureType = InvertedTIFF) then
  2887.                                         InvertPic;
  2888.                                 if odd(PixelsPerLine) then
  2889.                                     UnpackLines;
  2890.                                 UpdatePicWindow;
  2891.                             end;
  2892.                         err := fsclose(f);
  2893.                         RoiShowing := false;
  2894.                     end;
  2895.                 OpPending := false;
  2896.                 Changes := false;
  2897.             end; {with}
  2898.     end;
  2899.  
  2900.  
  2901.     procedure FindWhatToPrint;
  2902.         var
  2903.             kind: integer;
  2904.             WhichWindow: WindowPtr;
  2905.     begin
  2906.         WhatToPrint := NothingToPrint;
  2907.         WhichWindow := FrontWindow;
  2908.         if WhichWindow = nil then
  2909.             exit(FindWhatToPrint);
  2910.         kind := WindowPeek(WhichWindow)^.WindowKind;
  2911.         if (kind = PicKind) and info^.RoiShowing and measuring then
  2912.             kind := valuesKind;
  2913.         case kind of
  2914.             PicKind: 
  2915.                 if info^.RoiShowing then
  2916.                     WhatToPrint := PrintSelection
  2917.                 else
  2918.                     WhatToPRint := PrintImage;
  2919.             HistoKind: 
  2920.                 WhatToPrint := PrintHistogram;
  2921.             ProfilePlotKind, CalibrationPlotKind: 
  2922.                 WhatToPrint := PrintPlot;
  2923.             ValuesKind, ResultsKind: 
  2924.                 if mCount > 0 then
  2925.                     WhatToPrint := PrintMeasurements;
  2926.             TextKind: 
  2927.                 WhatToPrint := PrintText;
  2928.             otherwise
  2929.                 ;
  2930.         end;
  2931.         if (WhatToPrint = NothingToPRint) and (info <> NoInfo) then
  2932.             WhatToPrint := PrintImage;
  2933.     end;
  2934.  
  2935.  
  2936.     procedure UpdateFileMenu;
  2937.         var
  2938.             ShowItems, isSelection: boolean;
  2939.             i: integer;
  2940.             str, str2: str255;
  2941.     begin
  2942.         with info^ do begin
  2943.                 ShowItems := Info <> NoInfo;
  2944.                 isSelection := RoiShowing and (RoiType = RectRoi);
  2945.                 if OptionKeyWasDown and (CurrentKind <> TextKind) then begin
  2946.                         SetItem(FileMenuH, CloseItem, 'Close All…');
  2947.                         SetItem(FileMenuH, SaveItem, 'Save All');
  2948.                         SetMenuItem(FileMenuH, CloseItem, ShowItems);
  2949.                     end
  2950.                 else begin
  2951.                         SetItem(FileMenuH, CloseItem, 'Close…');
  2952.                         if isSelection and (CurrentKind <> TextKind) and (PictureType <> TiffFile) and (PictureType <> PictFile) and (CurrentKind = PicKind) then
  2953.                             SetItem(FileMenuH, SaveItem, 'Save Selection')
  2954.                         else
  2955.                             SetItem(FileMenuH, SaveItem, 'Save');
  2956.                         SetMenuItem(FileMenuH, CloseItem, ShowItems or (CurrentKind = TextKind) or (CurrentKind = ProfilePlotKind) or (CurrentKind = CalibrationPlotKind) or (CurrentKind = HistoKind));
  2957.                     end;
  2958.                 case CurrentKind of
  2959.                     ProfilePlotKind, CalibrationPlotKind: 
  2960.                         ExportAsWhat := asPlotValues;
  2961.                     HistoKind: 
  2962.                         ExportAsWhat := asHistogramValues;
  2963.                     ResultsKind: 
  2964.                         ExportAsWhat := asMeasurements;
  2965.                     PicKind:  begin
  2966.                             if (SaveAsWhat <> asPICT) then
  2967.                                 SaveAsWhat := asTiff;
  2968.                             if (ExportAsWhat > asText) then
  2969.                                 ExportAsWhat := asRaw;
  2970.                         end;
  2971.                     otherwise
  2972.                 end;
  2973.                 if isSelection and (SaveAsWhat <> AsPalette) and (CurrentKind <> ResultsKind) and (CurrentKind <> TextKind) then
  2974.                     SetItem(FileMenuH, SaveAsItem, 'Save Selection As…')
  2975.                 else
  2976.                     SetItem(FileMenuH, SaveAsItem, 'Save As…');
  2977.                 if isSelection and (ExportAsWhat <= AsText) then
  2978.                     SetItem(FileMenuH, ExportItem, 'Export Selection As…')
  2979.                 else
  2980.                     SetItem(FileMenuH, ExportItem, 'Export…');
  2981.                 for i := SaveItem to SaveAsItem do
  2982.                     SetMenuItem(FileMenuH, i, ShowItems or (CurrentKind = TextKind));
  2983.                 SetMenuItem(FileMenuH, ExportItem, ShowItems and (CurrentKind <> TextKind));
  2984.                 if isSelection then
  2985.                     str := 'Duplicate Selection'
  2986.                 else
  2987.                     str := 'Duplicate';
  2988.                 SetItem(FileMenuH, DuplicateItem, str);
  2989.                 for i := DuplicateItem to GetInfoItem do
  2990.                     SetMenuItem(FileMenuH, i, ShowItems and (CurrentKind <> TextKind));
  2991.                 if DataType <> EightBits then
  2992.                     str := 'Rescale'
  2993.                 else
  2994.                     str := 'Revert to Saved';
  2995.                 SetItem(FileMenuH, RevertItem, str);
  2996.                 SetMenuItem(FileMenuH, RevertItem, (Revertable or (DataType <> EightBits)) and (CurrentKind <> TextKind));
  2997.                 SetMenuItem(FileMenuH, PlugInExportItem, ShowItems);
  2998.                 FindWhatToPrint;
  2999.                 case WhatToPrint of
  3000.                     NothingToPrint: 
  3001.                         str := '';
  3002.                     PrintImage: 
  3003.                         str := 'Image';
  3004.                     PrintSelection: 
  3005.                         str := 'Selection';
  3006.                     PrintPlot: 
  3007.                         str := 'Plot';
  3008.                     PrintHistogram: 
  3009.                         str := 'Histogram';
  3010.                     PrintMeasurements: 
  3011.                         str := 'Measurements';
  3012.                     PrintText: 
  3013.                         str := 'Text';
  3014.                 end;
  3015.                 SetItem(FileMenuH, PrintItem, concat('Print ', str, '…'));
  3016.                 SetMenuItem(FileMenuH, PrintItem, WhatToPrint <> NothingToPrint);
  3017.             end; {with info^}
  3018.     end;
  3019.  
  3020.  
  3021.     procedure SaveAll;
  3022.         var
  3023.             SaveInfo: InfoPtr;
  3024.             i: integer;
  3025.     begin
  3026.         SaveInfo := Info;
  3027.         SaveAsWhat := AsTiff;
  3028.         SaveAllState := SaveAllStage1;
  3029.         for i := 1 to nPics do begin
  3030.                 Info := pointer(WindowPeek(PicWindow[i])^.RefCon);
  3031.                 SaveAs('', 0);
  3032.                 if CommandPeriod or (SaveAllState = NoSaveAll) then
  3033.                     leave;
  3034.             end;
  3035.         Info := SaveInfo;
  3036.         SaveAllState := NoSaveAll;
  3037.     end;
  3038.  
  3039.  
  3040.     procedure SaveScreen;
  3041.         var
  3042.             err, RefNum: integer;
  3043.             TheInfo: FInfo;
  3044.             name: str255;
  3045.             ok, NewFile: boolean;
  3046.             SaveInfo: InfoPtr;
  3047.             SaveNoInfoRec: PicInfo;
  3048.             ShutterSound: handle;
  3049.     begin
  3050.         name := 'Screen';
  3051.         err := GetVol(nil, RefNum);
  3052.         err := GetFInfo(name, RefNum, TheInfo);
  3053.         case err of
  3054.             NoErr:  begin
  3055.                     if TheInfo.fdType <> 'PICT' then begin
  3056.                             TypeMismatch(name);
  3057.                             exit(SaveScreen)
  3058.                         end;
  3059.                     NewFile := false;
  3060.                 end;
  3061.             FNFerr:  begin
  3062.                     err := create(name, RefNum, 'Imag', 'PICT');
  3063.                     if CheckIO(err) <> 0 then
  3064.                         exit(SaveScreen);
  3065.                     NewFile := true;
  3066.                 end;
  3067.             otherwise
  3068.                 if CheckIO(err) <> 0 then
  3069.                     exit(SaveScreen)
  3070.         end;
  3071.         ShutterSound := GetResource('snd ', 100);
  3072.         if ShutterSound <> nil then begin
  3073.                 err := SndPlay(nil, ShutterSound, false);
  3074.                 ReleaseResource(ShutterSound);
  3075.             end;
  3076.         SaveInfo := info;
  3077.         SaveNoInfoRec := NoInfoRec;
  3078.         with NoInfo^ do begin
  3079.                 PixelsPerLine := ScreenWidth;
  3080.                 nLines := ScreenHeight;
  3081.                 osPort := cScreenPort;
  3082.                 SetRect(PicRect, 0, 0, ScreenWidth, ScreenHeight);
  3083.                 LutMode := info^.LutMode;
  3084.                 cTable := info^.cTable;
  3085.             end;
  3086.         info := NoInfo;
  3087.         ok := SavePICTFile(name, RefNum, false, NewFile);
  3088.         NoInfoRec := SaveNoInfoRec;
  3089.         info := SaveInfo;
  3090.         if ok then
  3091.             PutMessage('The screen has been dumped to a PICT file named “Screen” in the same folder as Image.');
  3092.     end;
  3093.  
  3094.  
  3095.     function SuggestedExportName: str255;
  3096.         var
  3097.             name: str255;
  3098.     begin
  3099.         name := info^.title;
  3100.         case ExportAsWhat of
  3101.             asRaw, asMCID, asText:  begin
  3102.                     if name = 'Camera' then
  3103.                         name := 'Untitled';
  3104.                     if ExportAsWhat = AsText then
  3105.                         SuggestedExportName := concat(name, '(Text)')
  3106.                     else
  3107.                         SuggestedExportName := name;
  3108.                 end;
  3109.             AsLUT: 
  3110.                 SuggestedExportName := 'Palette';
  3111.             asMeasurements: 
  3112.                 SuggestedExportName := concat(name, '(Measurements)');
  3113.             AsPlotValues: 
  3114.                 SuggestedExportName := concat(name, '(Plot Values)');
  3115.             asHistogramValues: 
  3116.                 SuggestedExportName := concat(name, '(Histogram)');
  3117.             asCoordinates: 
  3118.                 SuggestedExportName := concat(name, '(Coordinates)');
  3119.         end;
  3120.     end;
  3121.  
  3122.  
  3123.     function ExportHook (item: integer; theDialog: DialogPtr): integer;
  3124.         const
  3125.             EditTextID = 7;
  3126.             RawID = 9;
  3127.             xyCoordinatesID = 16;
  3128.         var
  3129.             i: integer;
  3130.             fname: str255;
  3131.             NameEdited: boolean;
  3132.     begin
  3133.         if item = -1 then {Initialize}
  3134.             SetDialogItem(theDialog, RawID + ord(ExportAsWhat), 1);
  3135.         fname := GetDString(theDialog, EditTextID);
  3136.         NameEdited := fname <> SuggestedExportName;
  3137.         if (item >= RawID) and (item <= xyCoordinatesID) then begin
  3138.                 ExportAsWhat := ExportAsWhatType(item - RawID);
  3139.                 if not NameEdited then begin
  3140.                         SetDString(theDialog, EditTextID, SuggestedExportName);
  3141.                         SelIText(theDialog, EditTextID, 0, 32767);
  3142.                     end;
  3143.                 for i := RawID to xyCoordinatesID do
  3144.                     SetDialogItem(theDialog, i, 0);
  3145.                 SetDialogItem(theDialog, item, 1);
  3146.             end;
  3147.         ExportHook := item;
  3148.     end;
  3149.  
  3150.  
  3151.     procedure Export (name: str255; RefNum: integer);
  3152.         const
  3153.             CustomDialogID = 100;
  3154.         var
  3155.             where: Point;
  3156.             reply: SFReply;
  3157.             isSelection: boolean;
  3158.             kind: integer;
  3159.             SaveAsState: SaveAsWhatType;
  3160.     begin
  3161.         with info^ do begin
  3162.                 if (name = '') or (RefNum = 0) then begin
  3163.                         where.v := 50;
  3164.                         where.h := 50;
  3165.                         if name = '' then
  3166.                             name := SuggestedExportName;
  3167.                         SFPPutFile(Where, 'Save as?', name, @ExportHook, reply, CustomDialogID, nil);
  3168.                         if not reply.good then begin
  3169.                                 macro := false;
  3170.                                 exit(Export);
  3171.                             end;
  3172.                         with reply do begin
  3173.                                 name := fname;
  3174.                                 RefNum := vRefNum;
  3175.                                 DefaultRefNum := RefNum;
  3176.                             end;
  3177.                     end;
  3178.                 isSelection := RoiShowing and (RoiType = RectRoi);
  3179.                 case ExportAsWhat of
  3180.                     asRaw, asMCID:  begin
  3181.                             if ExportAsWhat = asMCID then
  3182.                                 InvertPic;
  3183.                             SaveAsState := SaveAsWhat;
  3184.                             if ExportAsWhat = AsRaw then
  3185.                                 SaveAsWhat := asRawData
  3186.                             else
  3187.                                 SaveAsWhat := SaveAsMCID;
  3188.                             if isSelection then
  3189.                                 SaveSelection(name, RefNum, false)
  3190.                             else
  3191.                                 SaveAsTIFF(name, RefNum, 0, 0, false);
  3192.                             SaveAsWhat := SaveAsState;
  3193.                         end;
  3194.                     AsText: 
  3195.                         ExportAsText(name, RefNum);
  3196.                     AsLUT: 
  3197.                         SaveLUT(name, RefNum);
  3198.                     asMeasurements: 
  3199.                         if mCount > 0 then
  3200.                             ExportMeasurements(name, RefNum)
  3201.                         else
  3202.                             PutMessage('Sorry, but no measurements are available to export.');
  3203.                     AsPlotValues: 
  3204.                         if PlotWindow <> nil then begin
  3205.                                 kind := WindowPeek(PlotWindow)^.WindowKind;
  3206.                                 case kind of
  3207.                                     ProfilePlotKind: 
  3208.                                         ConvertPlotToText;
  3209.                                     CalibrationPlotKind: 
  3210.                                         ConvertCalibrationCurveToText;
  3211.                                     otherwise
  3212.                                         TextBufSize := 0;
  3213.                                 end;
  3214.                                 SaveAsText(name, RefNum);
  3215.                             end
  3216.                         else
  3217.                             beep;
  3218.                     asHistogramValues: 
  3219.                         if HistoWindow <> nil then begin
  3220.                                 ConvertHistoToText;
  3221.                                 SaveAsText(name, RefNum);
  3222.                             end
  3223.                         else
  3224.                             beep;
  3225.                     asCoordinates: 
  3226.                         ExportCoordinates(name, RefNum);
  3227.                     otherwise
  3228.                         beep;
  3229.                 end; {case}
  3230.                 if (SaveAsWhat = asRawData) and (SaveAllState <> SaveAllStage2) then
  3231.                     SaveAsWhat := asTIFF;
  3232.             end; {with}
  3233.     end;
  3234.  
  3235.  
  3236.  
  3237. end.